Jump to content
IGNORED

Francis Ichabod Cranium 8 (was:"Missiles and coloring")


Recommended Posts

So I was playing around with a game idea involving a multi-colored sprite. And I got to wondering if the multicolored sprite had a missile, what color would it be? Would it be something similar to the "coin" in Mario Bros.? If not, then what else? Could I make the missile of player0 (the multi-colored sprite I have) its own one color? In the Celery game, I'm using missile 1 for the eyes and the incinerator door, that's why I didn't have the question then, since player1 in that case (the incinerator) was one color. But now I would like two multicolored sprites if possible, so if missile0 is the result of what happens in Mario Bros., I guess I could make the firing missile missile1 and have player1 all one color.

post-9475-0-07469500-1487194502_thumb.png

fice1.asm

Edited by atari2600land
Link to comment
Share on other sites

So anyway, I made a missile1, and I can control its Y starting position, but I can't find any documentation about how to set up a missile's X position. In this example, if you press fire, the missile's y position will be where I want it to be, but its x position will be at the left side of the screen instead of the left side of the player, where I want it to be. Also, I want some way to know once missile1x gets to the right side of the screen then stop moving and disappear.

So, what controls missile1x?

fice2.asm

Link to comment
Share on other sites

Check out RESMP0, RESM0, and HMM0 in the stella programming guide.

 

Essentially you can either position missiles centered on their corresponding player or position them as you would a player by strobing RESM0 and then using HMM0 to fine tune it.

 

Pairing P0&M1 and P1&M0 would work for producing to multicolor sprites as long as you can tolerate them having opposite color schemes. Otherwise you have to update COLUP0 and COLUP1 at just the right time. That means there must be enough horizontal space between sprites and you also have to have some precisely timed code. Best case for pulling this off would be if the sprites were each restricted to the left or right third of the screen.

 

EDIT: Just realized you meant multicolored in the traditional sense where the color is changed each scanline. In that case you can have each player be a multicolor sprite and the missile will just take on whatever color the player is that scanline. In other words the missile will be multicolor as well.

Edited by ZackAttack
Link to comment
Share on other sites

You should look at the Collect blog entry for missiles. The source code is attached at the bottom. In collect.asm there is a subroutine named PosObject, just use that to position your missiles horizontally. Don't forget that this routine only sets the HMxx registers. You still have to strobe HMMOVE and probably want to clear the move registers after you've called PosObject for all the objects you want to position.

;set missile0 x position to 74
lda #74 ; x position
ldx #2  ; missile0
jsr PosObject

;set missile1 x position to 95
lda #95 ; x position
ldx #3  ; missile1
jsr PosObject

;Strobe HMOVE
sta WSYNC
sta HMOVE
;Wait a scanline and strobe HMCLR
;You must not strobe HMCLR until at least 23 cycles after HMOVE or positions will be wrong
sta WSYNC
sta HMCLR


;PosObject routine from collect.asm

;===============================================================================
; PosObject
;----------
; subroutine for setting the X position of any TIA object
; when called, set the following registers:
;   A - holds the X position of the object
;   X - holds which object to position
;       0 = player0
;       1 = player1
;       2 = missile0
;       3 = missile1
;       4 = ball
; the routine will set the coarse X position of the object, as well as the
; fine-tune register that will be used when HMOVE is used.
;
; Note: The X position differs based on the object, for player0 and player1
;       0 is the leftmost pixel while for missile0, missile1 and ball 1 is
;       the leftmost pixel:
;           players     - X range is 0-159
;           missiles    - X range is 1-160
;           ball        - X range is 1-160
; Note: Setting players to double or quad size will affect the position of
;       the players.
;===============================================================================
PosObject:
        sec
        sta WSYNC
DivideLoop
        sbc #15        ; 2  2 - each time thru this loop takes 5 cycles, which is 
        bcs DivideLoop ; 2  4 - the same amount of time it takes to draw 15 pixels
        eor #7         ; 2  6 - The EOR & ASL statements convert the remainder
        asl            ; 2  8 - of position/15 to the value needed to fine tune
        asl            ; 2 10 - the X position
        asl            ; 2 12
        asl            ; 2 14
        sta.wx HMP0,X  ; 5 19 - store fine tuning of X
        sta RESP0,X    ; 4 23 - set coarse X position of object
        rts            ; 6 29
Link to comment
Share on other sites

Your code says otherwise.

ArenaLoop:                  ; - 11 - time of longest path here
	    cpy FrancisFeet
        bne DontDrawMissile			

		lda #2
		sta ENAM1
		
		lda #4
		sta COLUP1

Only the FrancisFeet variable controls if M1 is enabled. An easy fix would be to have a variable named ShowM1 and set it when you want the missile to change states.

ArenaLoop:                  ; - 11 - time of longest path here
	    cpy FrancisFeet
        bne DontDrawMissile			

		lda ShowM1
		sta ENAM1
		
		lda #4
		sta COLUP1
Link to comment
Share on other sites

open stella debug (press ~ key)
trapwrite ShowMissile1
resume execution (press ~ key)
never breaks
open stella debug (press ~ key)
break GameLoop
resume execution (press ~ key)
breakpoint is hit
step through code reveals that branch is taken at bmi IHateThis, this skips the check for Missile1X as well
Solution: Merge MissileFired and ShowMissile1 into a single variable. Treat this as a simple finite state machine (FSM). States are Missile1InFlight $02 amd Missile1ReadyToFire $00.
Renaming to Missile1State during the merge has the added benefit that the code will break in every place that the MissileFired and ShowMissile1 are used. So it won't assemble until every relevant spot has been reviewed and updated.
Still doesn't work. Stella debug reveals that Missile1X never changes. Add instructions to keep variable in sync with actual missile position.
Updated source attached.

fice3.asm

Link to comment
Share on other sites

I finally got the scanline to be a steady 262...but only if the player is on the left side of the screen. If he's on the right, when firing begins it jumps to 263 for two frames and then goes back down, a problem I was having all over the screen until I did something that fixed, but only on the left side. So I restricted his movement to only the left side. And also, when he went up to a certain point, he began to vanish. So another moving restriction was put into place. Why is the overscan number so low? I can't believe it, it wasn't this low for Cellar-y Celery. And yet all I have so far is a guy flying around on the left side of the screen and shooting stuff and it's already below 10. And I also wonder why the pixels that make up Francis jumped up to 2 pixels high instead of the one pixel high that was in the first version. Weird. Both versions are in this zip file I attached so perhaps one can look and see what went weird.

fice20170219.zip

  • Like 1
Link to comment
Share on other sites

The problem is that you've put the missile code in GameLoop which precedes GameLoop1.

GameLoop1:
			jsr VerticalSync
			jsr VerticalBlank
			jsr Kernel
			jsr Overscan1	
			jmp GameLoop
  • Move any code in GameLoop1 to Overscan or VerticalBlank subroutines.
  • Remove GameLoop1 since it should now be equivalent to GameLoop
  • Rename Overscan1 to just Overscan
  • Only ever have a single VSync, VBlank, Kernel, and Overscan routine/label.

This reason this is a problem is because the PositionPlayer subroutine you're using will take 1 or 2 scanlines to execute depending on the position it's setting. Since VerticalBlank and Overscan1 use the timer to determine when the right number of scanlines has passed they are agnostic to that detail. Basically you have 30 scanlines to execute some code in overscan, but it's ok if it takes less.

 

Also a style tip is to keep the subroutines located in your source file according to where they are in the call hierarchy. So the following order would be appropriate:

  • Reset:
  • GameLoop:
  • VerticalSync
  • VerticalBlank
  • Kernel
  • Overscan

Next would be any routines that are called from the routines I've already listed. The idea is that you should be able to open a source file and immediately get a feel for what it's doing at the highest level of abstraction. Then you can drill down further to get more details if desired.

 

Link to comment
Share on other sites

I worked some more on this and while I was working on it, a mysterious white line began appearing on the side of the screen at the same y position as the enemy (waffle. I've decided that the missile is a pencil and he's trying to shoot waffles.) I've tried a lot of stuff to get rid of the white line but it won't leave. It appears to be part of the playfield. Why is it there, and how can I get rid of it? In the zip file are the bin and asm files.

fice6.zip

post-9475-0-00869700-1488005191_thumb.png

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...