|
ForumsSega Master System / Mark III / Game GearSG-1000 / SC-3000 / SF-7000 / OMV |
Home - Forums - Games - Scans - Maps - Cheats - Credits Music - Videos - Development - Hacks - Translations - Homebrew |
![]() |
Goto page 1, 2 Next |
Rate this entry!
This poll has expired.
|
||||||||||||||||||||||||||||
Author | Message | |||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
[Coding competition 2015] Racer by hang-on
![]() |
|||||||||||||||||||||||||||
http://www.smspower.org/Homebrew/Racer-SMS
|
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
In case you skimmed through the description. This entry comes with a super detailed article:
http://www.smspower.org/Articles/CreateARacingGame |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
It's amazing... how much I suck at this game! I'm just LOLLing so much... thanks for it! :D | ||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Haha, thanks - you are welcome :) To keep you motivated, I can say that my son (6 years old) holds an impressive hiscore of 1917. And for myself: I can't beat it yet (9999), but have passed the 3k mark... |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Wow, it's fun, and thank you for the amazing article!
My best score is 630, I don't understand how I got so far... I never played the original, but your version seems faster and with more dangerous other cars. It makes you see life in green when it stops! :) |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
It play really well for such an old and simple game. The recreation feels very legit, even the engine sound feels in line with what I'd expect from that previous generation of game.
Only criticism is is the reset timer is a bit slow, it's frustrating to wait so long between attempts :) 1179 points.. 1400 something.. |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Thanks guys :) Having the original to aim for really helped me stay focused, not wandering off in random directions.
Point taken about the death delay. I think it is important to have one, but I can reduce it a little in the next version. For aspiring Racer-drivers to judge their performace, I paste this chart from the readme: Name Age Hiscore Quote
------------- --------- ------ ----------------------------- Lasse 6 1917 Hmmm, this game needs more Skylanders! Luna 13 390 What are those things - are they cars?!? Pia n.a. 401 Good job, hon. But will it make us rich? -------------------------------------------------------------- |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
LOL, I got a similar response from my partner when I showed her my game. ;-) |
||||||||||||||||||||||||||||
![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Maybe there's a first part of the delay that cannot be skipped with a keypress (say, 0.5 seconds? 1 second). And another half that can be skipped.
Loved the chart too. |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Really nice. I totally suck at it. Thanks for the excellent article. It would be cool to see more "Making Ofs" like this in the future. | ||||||||||||||||||||||||||||
![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Thanks! The game should be played in intense, short bursts. Perfect for a hot seat party play session. Thus it should be frustrating hard, but not too hard. Maybe I can tweak it a little so that it will become a little easier. The game could wait a little longer until it throws in the second enemy car.Or the enemy cars could take it a little slower vertically. | ||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() Last edited by Bock on Mon Mar 30, 2015 12:32 pm; edited 1 time in total |
|||||||||||||||||||||||||||
Oh no don't make it easier! I think it hits a sweet spot now - it keeps you on your toes. If it was easier it may become just very boring? | ||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Yeah - that was actually my motivation for changing the original 2 minute racing time of Speedway! to this one-life score-chasing game mechanic. Two minutes guaranteed life is simply too boring :) | ||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
878 so far... | ||||||||||||||||||||||||||||
![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
@Tycho: Nice. Keep going! :)
Input wanted: Pressing the pause button will instantly kill you on real hw...?! I cannot explain why, but maybe some of you guys can shed some light on the issue. This is my interrupt routines: ; Read the vdp status flag at every frame interrupt.
; Sprite collision is read from bit 5 of the status flag. .orga $0038 ; frame interrupt address. ex af,af' ; save accumulator in its shadow reg. in a,$bf ; get vdp status / satisfy interrupt. ld (status),a ; save vdp status in ram. ex af,af' ; restore accumulator. ei ; enable interrupts. ret ; return from interrupt. ; Disable the pause button - this is an unforgiving game! .orga $0066 ; pause button interrupt. retn ; disable pause button. I use the vdp status flag to handle collision: ; Test for collision between sprites.
ld a,(status) ; load vdp status (set by interrupt). bit 5,a ; is the sprite collision bit set? jp nz,plrdie ; yes - jump out of main loop. So my theory is that invoking the pause button interrupt somehow interferes with the vdp status port?! |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Pause will hit the stack which would cause trouble if you are doing something funny with it. Otherwise I can't see anything wrong. | ||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
But if it is the way I use the stack, then emulators would replicate the error, I guess? | ||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Yes, unless there's any timing sensitivity. Are you explicitly changing the stack pointer anywhere? | ||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
No. I don't think so. Just very conservative use of push, pop and call instructions for the stack.
I have even tried to make this workaround this morning: .orga $0066 ; pause button interrupt.
push hl ; save HL on the stack. ld hl,status ; point to vdp status variable. res 5,(hl) ; reset the sprite collision bit. pop hl ; restore HL from the stack. retn ; So when you press pause, you actually reset the collision bit in the variable that is used for collision detection. But it has no effect on real hw..? Press pause and kill the player... Hmmm... |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
I don't get it. NMI should call your routine at $0066 and you're just retn from there. I wonder if it's happening on your hardware only. | ||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Does it reliably kill the player on each press of the pause button?
I just managed to kill the player by frequently pressing the pause button in Emulicious. But I also have no idea yet how this makes sense... |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Ah, this is actually a little soothing to hear :) thanks for the co-investigation. Yes, on hardware just one hit on pause kills the player straight off. I have tried the pause in both Emu and Meka, but I could not reproduce the killing. But maybe I was not persisting enough :) |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Well the problem is that emulators are going to poll the pause input button (e.g. space bar in meka) at a certain time in the emulated frame and emulation is likely to be always at the same point.
( There was this discussion http://www.smspower.org/forums/8426-PAUSE http://www.smspower.org/Homebrew/PauseTest-SMS I seem recall someone (maybe FluBBa) made an experiment to try to record when pause happened? ) |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Ah - relevant link. Inspired by that discussion, I tried to change ret to reti in my maskable interrupt handler, but it does not change anything. Still a lethal pause button. .orga $0038 ; frame interrupt address.
ex af,af' ; save accumulator in its shadow reg. in a,$bf ; get vdp status / satisfy interrupt. ld (status),a ; save vdp status in ram. ex af,af' ; restore accumulator. ei ; enable interrupts. reti ; return from interrupt. ; Disable the pause button - this is an unforgiving game! .orga $0066 ; pause button interrupt. push hl ; save HL on the stack. ld hl,status ; point to vdp status variable. res 5,(hl) ; reset the sprite collision bit. pop hl ; restore HL from the stack. retn ; disable pause button. |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
I think I just identified your issue:
You're expecting VBLANK when the HALT instruction is left. But an NMI will also make the Z80 leave the HALT. While you're expecting VBLANK you're actually during active display. During that time you're writing your SAT using OTIR and that way kinda corrupt your sprite data which seems to quickly produce colliding sprites. |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
I think you nailed it! Super! My pause hitting does cause glitchy graphics, so it could very well be as you described. I'll look into it. Thanks a lot! | ||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Pause button bug finally ironed out! Following your lead, Calindro, I have made a wait for vblank subroutine:
; --------------------------------------------------------------
; Wait for end of active display (0-191). wait in a,($7e) ; read vertical position register. cp $c0 ; are we at line 192? jp nz,wait ; no - loop back. ret ; else - fall through and return And instead of starting my main loop with a halt opcode, I call this function instead: ; This is the main loop. mloop call wait :) Thanks for the support! |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Polling the line counter is bad, better to set a flag in the VBlank handler and halt + poll that. | ||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Why is it bad? | ||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
On PAL systems you can see that value at two different places in the display, so your timing is all wrong. | ||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
I see. Thanks for the feedback, Maxim! I have changed things into a flag-based approach:
I have a one-byte interrupt flag (iflag) and an interrupt handler like this: ; Read the vdp status flag at every frame interrupt.
; Sprite collision is read from bit 5 of the status flag. ; Set the frame interrupt flag. .orga $0038 ; frame interrupt address. ex af,af' ; save accumulator in its shadow reg. in a,$bf ; get vdp status / satisfy interrupt. ld (status),a ; save vdp status in ram. ld a,1 ; load accumulator with raised flag. ld (iflag),a ; set interrupt flag. ex af,af' ; restore accumulator. ei ; enable interrupts. reti ; return from interrupt. And then the wait subroutine is polling the flag like this: ; --------------------------------------------------------------
; Wait for vertical blanking phase. wait ld a,(iflag) ; get the frame interrupt flag. cp 1 ; is it set? jp nz,wait ; no? - keep looping. xor a ; else - reset flag. ld (iflag),a ; update the frame interrupt flag. ret ; return. At the start of the main loop, I call the wait routine. Works on real hw :) |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Tips:
- The status flags are non zero so you can just save them, no need to load 1 - To check for non zero, use "or a". This will set the z flag accordingly. - So you actually don't need the iflags at all, just use status and zero it when done. - If you put a halt into the polling loop then it will allow emulators to optimise and save battery on mobile devices. - I see you're going for a retro assembly style but anonymous or local labels would be better than a regular top level one. |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
OK, thanks for the tips. "Emulators on mobile devices..." - it makes me feel like I'm missing out on something with my Ipad :)
I don't think I can zero the status flag, since I'm using it for collision detection later in the loop. |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Hi guys.
New version is added to Racer's page in the Homebrew section. Enjoy the limited Easter Edition of Racer. The palette is tweaked according to the season, so expect happy Easter colors which are also softer on the gamer's eyes (compared to retro purple, at least). Both the regular and the easter edition is included in the zip file, with the following updates: • Smaller death delay means you are more swiftly back on the track for another race... if (when?) you die! Thanks Bock. • Real hw pause bug was finally taken care of. Thanks Calindro and Maxim. |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Works flawlessly on hardware (well, you already know that...) and it's in no way easier.
Pure fun. I can't stop laughing... and get past 540 points. |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Haha - thanks a lot! That race track is surely an unforgiving place :) | ||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Very entertaining yet unforgiving. I tried both versions on a gaming tablet attached to a LED TV via HDMI. And the original version surely is hard to watch. I liked the Easter version much more because of decreased difficulty and better colours (easier on the eyes). But both are great.
I just can't imagine what would happen if you decided to release a Xmas version in December. Red on green... Ouch! My eyes! :-P |
||||||||||||||||||||||||||||
![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Thanks Tincho - I'm glad you like the game and the new Easter edition. It must be pure color psychology, because the game did not become easier with the newest version (unless I accidentally changed some bytes here and there). But maybe the happy colors accomodate sharper reflexes. Who knows? :)
Haha, great idea for a Christmas release. I'll be back when the snow starts to fall... |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
I have a question about Racer, forgive my lateness. I was looking through the code and was wondering where the score was. There's no mention of it in the code, or how to raise it, or even display it. I would like to have a score in my game, and an example of how to do a score would help a lot. | ||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
There are many ways to do it, this game seems (from a quick look at the code) to store it as one byte per digit, with custom routines for maths to add to the score. The format makes maths hard but display easy, plus it is extensible to arbitrary numbers of digits. | ||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
I can't figure out the collision detection in this game. I tried to put collision detection in my game using this game's collision detection but it won't work. | ||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Racer actually does not do 'proper' collision detection. It just checks the internal flag that gets set automatically when any two sprites overlap. For Racer, this is perfectly sufficient. For a less simple game, you'll need something more sophisticated. I suggest you read the Spectrum tutorial that's linked in the "Getting started" section. It explains collision routines quite nicely. |
||||||||||||||||||||||||||||
![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
That link leads to a bunch of ZX Spectrum homebrew games to download, and I didn't see a tutorial on there anywhere, unless I missed it somehow.
EDIT: Oh, it's at the bottom. I clicked on the link and it says it's "currently unavailable." |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
You can find an older version here: https://chuntey.wordpress.com/tag/jonathan/ |
||||||||||||||||||||||||||||
![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Hi!
Thanks for your interest in Racer and the tutorial, Gamegearguy. I'm sorry I have not reacted sooner, but I have been away from the forum, and my topic activity notifications seem to go into the spam filter :( Maxim and Kagesan are of course right. Scorehandling is more or less taken from Jonathan Cauldwell's Spectrum coding tutorial. I can add an explanation to the tutorial if you still need it. And yes - the collision detection is the vdp flag. It works because no sprites do ever collide, except for when the player collides with an enemy car :) |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Hello guys.
Christmas is fast approaching, and I promised TinchoDJ to be back with a revised edition of Racer when the snow started to fall. In Denmark, we have just been hit fast and hard with a plenty of snow, and thus it is my pleasure to present Racer - rebooted! I have re-written it from the ground up, and used the forum feedback for inspiration and encouragement. |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Pretty nice update! Nice graphics, simple but fun gameplay. | ||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Looks fantastic great job | ||||||||||||||||||||||||||||
![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Thanks both of you - I'm glad you like it!
Regarding the visuals, some credit is due: The racing car sprites are modified versions of sprites from another SMS racing game. But which one is it...? :) - and the text is based on output from http://nfggames.com/games/fontmaker/. |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
||||||||||||||||||||||||||||
|
![]() |
|||||||||||||||||||||||||||
Very nice! :) It's much simpler than the previous game, I could even score 52!
A suggestion: using up/down the player should be able to speed up/slow down, and the Y position of the car should be tied to its speed so that the faster the car goes the higher it appears on screen. So one can play exactly like this, never accelerating, or play faster :) |
||||||||||||||||||||||||||||
![]() ![]() ![]() |
![]() |
Goto page 1, 2 Next |