Ice Blocks

ZeGGamer1

New member
Hey, does anyone know if there is a way to create a solid tile that changes the acceleration of the player when standing on it?
 

ZeGGamer1

New member
Of course, I don't know if this is the way that one would go about making ice blocks, but it was just a suggestion.
 

dale_coop

Moderator
Staff member
Should be difficult, I think some members did that kind of tiles already. Would be nice if they could share some part of their script or hint to do that.
I could take a look tonight or tomorrow ;)
 

dale_coop

Moderator
Staff member
ZeGGamer1 said:
Any Progress?


Made some quick tests...

Modify the "HandleUpdateObject" script (in the Routines\System\ folder), at line 319, you should see:
Code:
	LDA ObjectAccAmount,y
	STA tempAccAmount
Replace those lines with :
Code:
	;; object is on ice?
	LDA Object_physics_byte,x
	AND #%00010000
	BEQ +
	LDA #$08	;;<<-- HEREthe new acceleration value (low value gives inertia)
	JMP ++
	+
	LDA ObjectAccAmount,y
	++
	STA tempAccAmount

Modify the script assigned to your "Handle Tile Collisions" in the "Project Settings >Script Settings", and around line 27, just after the "STA navFlag" line, add those lines:
Code:
	;;re-init the on Ice bit (bit 4)
	LDA Object_physics_byte,x
	AND #%11101111
	STA Object_physics_byte,x

Make a new script "IceSolid.asm" in your "ModuleScripts\TileScripts\ScrollingPlatformer" folder (or AdventureGame", ... depending of your game's type), with :
Code:
	;; set the ice bit:
	LDA Object_physics_byte,x
	ORA #%00010000
	STA Object_physics_byte,x
	
	; if plateformer game, you neeed those lines too (else, comment them out):
	LDA #TILE_SOLID
	STA tile_solidity

Assigned the script to an unused "Tile Collision 0?" in the "Project Settings > Script Settings". And finally change the label accordingly (in the "Project Labels" tab, "12 - NULL" to "12 - Ice").
 

ZeGGamer1

New member
I tried doing that, but my player glitches out visually and doesn't slide. I used tile collision 15, would that have any affect?
 

ZeGGamer1

New member
I would show a video of what is happening, but I the forums won't let me upload a video, but It seems like standing idly on the ice makes the player animate faster, despite not having a player idle animation.
 

dale_coop

Moderator
Staff member
Tested on a platformer, with Collision Tile 15, it works fine.

What module are you using ? (plateformer/adventure,)
Could you share your scripts ("HandleUpdateObject.asm", ""Handle Tile Collisions" one and "soldIce.asm")?
 

ZeGGamer1

New member
Handle Update Object

Code:
HandleUpdateObjects:	




	JSR DrawAllSpritesOffScreen
	;; load the animation bank, as it has the lut tables in it, etc.
	;; at the beginning of the handle objects loop, we want to reset the counter to $0200
	;; (maybe, unless it's going *backwards* to allow for native flicker).
	;; since the high byte of this will always be #$02, we really only need to worry about one byte.
	;; this is spriteOffset.  A value of #$00 will result in writing to 0200.  A value of
	;; 05 will result in writing ot 0205.  a value of 80 will result in writing to 0280.

;;////////////////////////////////
	;;;; IF YOUR GAME DOES NOT REQUIRE DEPTH, COMMENT OUT THIS LINE TO MAKE IT PERFORM A BIT FASTER
	JSR UpdateDrawOrder
;;////////////////////////////////////
;;;;; IF YOUR SPRITE USES SPRITE ZERO HIT DETECTION 
;;;;; PUT THAT SPRITE ZERO DATA HERE
	;LDA #$18 ;; SPRITE 0 Y
	;STA $0200
	;LDA #$0f ;; SPRITE ZERO TILE
	;STA $0201
	;LDA #%001000011 ;; SPRITE ZERO ATTRIBUTE (uneccesary)
				;++-- sup pal to use
		;;;;+-------- use a 1 in bit 6 to put sprite in front of or behind background (hud)
;	STA $0202
	;LDA #$F8 ;; SPRITE ZERO X ;; make higher than #$07, lower than #$ff
	;STA $0203
	
	LDA #$00 ;; this is 4 if we need to use sprite 0 hit
	STA spriteOffset
	
	LDA currentBank
	STA prevBank
	LDY #$14
	JSR bankswitchY
	JSR doPreDraw
	LDY prevBank
	JSR bankswitchY


	LDA currentBank
	STA prevBank
	LDY #BANK_ANIMATIONS
	JSR bankswitchY

;;; here, we need to make x the value of
;; the first value in the Draw Order array.	
;; if you do not use draw order,just load X with zero here, and comment out storing it to DrawOrderTemp.
	LDX #$00
	TXA 
	STA DrawOrderTemp
UpdateObjectsLoop:
;;;;;;; ////////
;;COMMENT THESE NEXT TWO LINES OUT IF NOT USING DRAW ORDER
	LDA drawOrder,x
	TAX 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;




	LDA Object_status,x
	AND #OBJECT_IS_ACTIVE
	BEQ thisObjectIsInactive
	JMP thisObjectIsActive
thisObjectIsInactive:
	;; it is not active, but are we about to turn it on?
	LDA Object_status,x
	AND #OBJECT_ACTIVATE
	;; if this bit if slipped, that means we need to activate this object in this frame.
	;; which means any data the object needs to gather, it can do so here.
	BNE thisObjectNeedsToBeActivated
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	;LDA #$00
	;STA Object_x_hi,x
	;STA Object_y_hi,x

	;;; it does not need to be activated.
	;; check to see if it needs to be deactivated?
	JMP doneUpdatingThisObject
thisObjectNeedsToBeActivated:


	;;; do the loads for this object.  All we know right now are x,y,and type
	
	;LDA #OBJECT_IS_ACTIVE
	LDA Object_status,x
	ORA #%10000000
	AND #%10111111
	STA Object_status,x
	;;;; done with the loads for this object.  Now, it is active, and can flow right
	;; into what happens to the object if it's active (maybe skip beyond update movement?)
	;; WHICH WILL STILL BE IN ANIMATION BANK, so no need to change back now.
	;; do we even need to populate bytes?  Some.  Ones like health and timers and such.
		
		;;; load action timer
		;;; load animation speed
		;;; load vulnerability for action 1
	LDY Object_type,x
		
			LDA VulnerabilityTableLo,y
			STA temp16
			LDA VulnerabilityTableHi,y
			STA temp16+1
			LDA Object_action_step,x
			AND #%00000111
			TAY
			LDA (temp16),y
			STA Object_vulnerability,x
			
		LDY Object_type,x
			LDA ObjectFlags,y
			STA Object_flags,x
			
			
		;;; read a status bit (do this above) to get direction, spawn action, etc?
		;;;;;====================
		;; Storing these values prevent us from having to do 
		;; a double lookup every frame

		LDY #$16
		JSR bankswitchY
		
		LDY Object_type,x
		LDA ObjectLoSpriteAddressLo,y
		STA Object_table_lo_lo,x
		LDA ObjectLoSpriteAddressHi,y
		STA Object_table_lo_hi,x
		
		LDA ObjectHiSpriteAddressLo,y
		STA Object_table_hi_lo,x
		LDA ObjectHiSpriteAddressHi,y
		STA Object_table_hi_hi,x
		
		LDY #BANK_ANIMATIONS
		JSR bankswitchY
		LDY Object_type,x
			;; things to happen BEFORE activating and zeroing out the rest of status.
		LDA Object_total_sprites,y ;; y represents the type of object.
									;; Object_total_sprites is a table in ObjectInfo that declares
									;; how many sprites total that an object has.
		STA Object_total_tiles 

		
		

		;;;; set animation frame to zero
		LDA #$00
		STA Object_animation_frame,x
		JSR setActionTimer
		
		JSR getNewEndType
		
		
		;; must be in anim bank
		JSR getAnimationSpeedAndOffset
	

		LDY Object_type,x ;; restore y
		;;///////////////////// Load other pertinent details for object here
		
		LDA ObjectHealth,y
		STA Object_health,x
		CPX player1_object
		BNE nevermindDoPlayerSpecificLoads
		;;;;;;;;;;;;;;;;;; is player
		;;;;;;;;;;;;;;;;;; do player specific things.
		LDA Object_scroll,x
		STA xScroll_hi
	
;dontDoPlayerSpecificThings:		
		
;		CPY #$00
;		BNE nevermindDoPlayerSpecificLoads
		;; do player specific loads.
		;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		;;DOES GAME PLAYER HAVE HEALTH?
		
			;LDA Object_health,x
			;STA myHealth
			;LDA #BOX_0_ASSET_1_TYPE ;; by default, health.
			;CMP #$FF ;; the health gets attached not at screen load, but at object load.
					;; because of this, we need to see if it's drawn.  If it is NOT
					;; drawn, and we do this, it'll never get turned off, and the rest
					;; of our hud won't function.
					;; FF means null.
			LDA #HUD_LOAD	
			AND #%01000000
			BEQ +
			STA hudElementTilesToLoad
			LDA #$00
			STA hudElementTilesMax
			; LDA DrawHudBytes
			; ora #HUD_myHealth
			; STA DrawHudBytes
			
			UpdateHud HUD_myHealth
			;Load hud stuff
			;; TURN ON handling the hud
		
			LDA #BOX_0_ASSET_0_MAX_VALUE
			STA hudElementTilesFull
			
			LDA #$00
			STA updateHUD_offset	
		+
			LDA Object_movement,x
			AND #%11111000
			ORA #STARTING_DIRECTION
			STA Object_movement,x
				
		nevermindDoPlayerSpecificLoads:
		;;;;;;;;////////////////////////////////////
			;;; Set up bounding box
			LDA ObjectBboxLeft,y
			STA Object_left,x
			CLC
			ADC ObjectWidth,y
			STA Object_right,x
			LDA ObjectBboxTop,y
			STA Object_top,x
			CLC
			ADC ObjectHeight,y
			STA Object_bottom,x
	
			LDA ObjectWidth,y
			LSR
			CLC
			ADC Object_left,x
			STA Object_origin_x,x ;; center
			LDA ObjectHeight,y
			LSR
			CLC
			ADC Object_top,x
			STA Object_origin_y,x ;; center
	
	
		;LDA currentNametable ;; must i do a check to see where scroll is, and if it should be in right nametable?
		;STA Object_scroll,x
	
		LDA ObjectReaction,y
		STA Object_edge_action,x
		;;;============================================
		JSR DoNewAction	
	
		;;etc
		;;; load 
	;; do the initial first action.	
	JMP doneUpdatingThisObject ;; this object just came into being.  it will ignore animation / update
						;;otherwise it will be beyond frame 0 and into frame 1 before we even see it.
		
thisObjectIsActive:
	;; if it's active, we need to do two things.  One, update it's movement, animation, etc, which we would do first.
	;;; at the top of the update, we need to make sure this object is respectding its vulnerability byte and action timer updates.

	LDA Object_state_flags,x
	ANd #%11011111
	STA Object_state_flags,x	
	
	LDA Object_state_flags,x
	AND #%10000000 ;; does it need to update its action timer?
	BEQ +
	JSR setActionTimer
	LDA Object_state_flags,x
	AND #%01111111
	STA Object_state_flags,x
	

	
+
	LDA Object_state_flags,x
	AND #%01000000
	BEQ +
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Reset bit 6 of Object_state_flags.  Only if it collides with
;; an object that should be 'above it' should it be ticked.

	;; now only proper collision will trip this for each object.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	LDY Object_type,x


		LDA VulnerabilityTableLo,y
		STA temp16
		LDA VulnerabilityTableHi,y
		STA temp16+1
		LDA Object_action_step,x
		AND #%00000111
		TAY
		LDA (temp16),y
		STA Object_vulnerability,x
	+		
		LDY Object_type,x
	
	
UpdateObjectMovement:
	;;;;;; DO WE UPDATE OBJECTS, OR ARE GAME OBJECTS FROZEN?
;;;; 
	LDA gameHandler
	AND #%00110000 ;; objects bit
		;; bit 5 = if textbox is turning on.
		;; bit 4 = if a tiles are updating, like when a switch is flipped.
	BEQ doHandleObjects
	JMP UpdateDrawObject
doHandleObjects:
	LDA currentBank
	STA prevBank
	LDY #BANK_ANIMS
	JSR bankswitchY

	LDY Object_type,x
	LDA ObjectMaxSpeed,y
	STA tempMaxSpeed
	;; object is on ice?
	LDA Object_physics_byte,x
	AND #%00010000
	BEQ +
	LDA #$08	;;<<-- HERE the new acceleration value (low value gives inertia)
	JMP ++
	+
	LDA ObjectAccAmount,y
	++
	STA tempAccAmount
	
	LDY #$14
	JSR bankswitchY

	JSR CalculateAccAndSpeed
	JSR HandleTileCollision
	JSR HandleCamera
	LDY prevBank
	JSR bankswitchY
	
	

	
	JSR HandleActionTimerUpdate
	JSR HandleObjectTimers
	

	;;;;;;;;;;;;;;;;;;;;;;;
	;; HANDLE SCROLL HERE.

	
	CPX player1_object
	BNE dontScrollUpdate
	JSR HandleScroll
dontScrollUpdate:


UpdateDrawObject:


	JSR getAnimOffset
	LDA Object_status,x
	AND #%00000100 ;; is it off screen but active?  if so, don't update it!
	BNE doneUpdatingThisObject
	
	JSR HandleDrawingSprites


	
	
doneUpdatingThisObject
;;; REMOVE THIS if not using draw order
	INC DrawOrderTemp
	LDA DrawOrderTemp
	TAX 
;;;;;;;Uncomment below if not using draw order.
	;INX
	CPX #TOTAL_MAX_OBJECTS 
	BEQ doneUpdatingObjects
	JMP UpdateObjectsLoop
	
doneUpdatingObjects:	
	;;;;; handle player object timer.
	LDA playerTimer_state
	AND #%00000001
	BEQ + ; no activer timer.
	;; the timer was active.
	LDA playerTimer_lo
	SEC
	SBC #$01
	STA playerTimer_lo
	LDA playerTimer_hi
	SBC #$00
	STA playerTimer_hi
	
	LDA playerTimer_lo
	CLC
	ADC #$00
	LDA playerTimer_hi
	ADC #$00
	BNE +
	;;;; finished player timer
	LDA playerTimer_state
	AND #%11111110
	STA playerTimer_state
	.include SCR_PLAYER_TIMER_1
+

	


	
UpdateObjectCollisions:
	LDA currentBank
	STA prevBank
	LDY #$14
	JSR bankswitchY
	
	JSR HandleObjectCollisions
	
	
	JSR countAllMonsters
	
	LDY prevBank
	JSR bankswitchY
	
	LDA #$01
	STA checkForSpriteZero
	RTS


Handle Tile Collisions (PS, there was only a script called Tile Collisions, none that said Handle Tile Collisions)



Code:
HandleTileCollision:
    ;;;;;ASSUMES vulnerability bit 000x0000, if one, skips collision.
    ;;;;;Six collision points. 
    ;;;;;All collision points checked and registered for all objects.
    ;;;; a solid in any of the points will result in negating all others.
    
        ;;; There are 6 ram variables, collisionPoint0 - collisionPoint5.
        ;;; collisionPoint0 = top left
        ;;; collisionPoint1 = top right
        ;;; collisionPoint2 = bottom right
        ;;; collisionPoint3 = bottom left.
        ;;; collisionPoint4 = mid left
        ;;; collisionPoint5 = mid right.
    
    TXA 
    STA currentObject
    TYA
    STA tempy

	LDA npc_collision
	AND #%11111101
	LDA #$00
	STA npc_collision
	LDA navFlag
	AND #%11111110
	STA navFlag
	;;re-init the on Ice bit (bit 4)
	LDA Object_physics_byte,x
	AND #%11101111
	STA Object_physics_byte,x
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; EXPLANATION:
;; In this basic module, both non gravity and gravity scripts are loaded.
;; Under most circumstances, a user will likely make use of one or the other,
;; as they each take up a good chunk of data.  But the benefit of including both is that
;; a platforming game with gravity is just a simple bit flip in the screen flags.
    
    
    LDA screenFlags
    AND #%00100000
    BNE useGravity
    JMP dontUseGravity
useGravity:
	LDA Object_vulnerability,x
	AND #%00100000
	BEQ useGravity2
	LDA Object_physics_byte,x
	AND #%00000010
	BNE useGravity2
	JMP dontUseGravity
useGravity2:

;;;;;;===================================================
;;;;;;***************************************************
;;;;;; TILE COLLISION FOR SCROLLING PLATFORMERS:
;;;;;; For scrolling platformers we will use three types of collision detection:
;;;;;;          1. A routine to check under our feet to determine
;;;;;;              whether or not you are standing on a solid object.

                    ;;; This function will check under neath the object's feet
                    ;;; by arg0 pixels.
                    ;;; it will update bit 0 of the Object_physics_byte.
                    ;;; If that bit is 0, it means the place is free.
                    ;;; If that bit is 1, it means the place is solid.
    ;**********************
       CheckUnderObject #$01

;;;;;;
;;;;;;          2. A routine that checks to see if the potential position leaves you
;;;;;;              with your 'bottom' or 'top' in a solid object, in which case it ejects pixel perfect
;;;;;;              to that tile.

                    ;;; This function checks the POTENTIAL vertical position.
                    ;;; If it results in a point in a solid object, it appropriately
                    ;;; ejects and places the object directly against the point
                    ;;; of collision.
    ; **********************
     CheckForVerticalEjection



SolidIce

Code:
	;; set the ice bit:
	LDA Object_physics_byte,x
	AND #%00010000
	STA Object_physics_byte,x
	
	; if plateformer game, you neeed those lines too (else, comment them out):
	LDA #TILE_SOLID
	STA tile_solidity
 

dale_coop

Moderator
Staff member
Ok, I see the problem.
Moify your "SolidIce.asm" script :
Code:
;; object on ice:

	LDA #TILE_SOLID
	STA tile_solidity
	
	;; we will use the bit 4 for on ice:
	LDA Object_physics_byte,x
	ORA #%00010000
	STA Object_physics_byte,x

Sorry, it was my mistake (typo error), I fixed it in the previous post.


Small off topic, when you write/copy/paste script on the forum, use the [ code ] tag, around your code (I edited your post). It will make it easier to read (and easier to copy/paste)

2019-03-07-09-51-33-NESMakers-Edit-post.png
 

Raftronaut

Member
I am wondering if this tile type can be adapted to a zero gravity situation?
Looking for A method to create a tile to change my player speed and acceleration. It would have to act as a null value to allow the player to pass through it while changing the acceleration/and player speed.
 
Top Bottom