It is currently Mon Dec 17, 2018 6:26 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 2 posts ] 
Author Message
PostPosted: Tue Nov 13, 2018 12:06 pm 
Offline
User avatar

Joined: Wed Sep 07, 2005 9:55 am
Posts: 339
Location: Phoenix, AZ
So I've been playing around with procedurally generated content and thought some sort of turn-based rogue-lite would be a good canidate because the rules and graphics are* pretty simple. The result is a sort of turn-based-action thing.

The player can pick what type of character they want to be, each having different stats. Instead of having the agility/movement stat control how many squares you can move each turn, I have it control how many turns you must wait to perform an action. Each turn can be classified as either a WAIT or an ACTION turn. WAIT frames just decrement the actors counter and return. ACTION turns can be whatever.

Originally, I had it perform one actor's turn per frame. This made the player input response lag. It would only register on NEW presses when the player was on an ACTION turn, causing a lot of NEW presses to become considered OLD by the time the player's ACTION turn came around.

I then had it execute as many turns each frame as it takes to get to the first ACTION turn for any actor. This greatly reduced the dropped input, but not completely. I'm assuming some sort of buffering would be needed. You can't buffer everything, otherwise pressing a direction would cause the player to shoot across the screen until it hit something solid. Maybe only start buffering after all buttons have been released? Maybe the entire thing is flawed. I thought about running turns until a player ACTION turn is hit, but the processing *could* take multiple frames, and would mess up the sprite0 hit.


Here's a diagram breaking down the problem. The numbers inside {} show the value of the counter after that turn is executed, ACTION denotes that the actor does something (like moving or attacking), and the "_state" denotes state changes within the actor itself.

note: All actors start in wait_state. When a player ACTION turn hits, the turn counter is not updated until the player actually does something. It will not skip the player.

Code:
=====Frame[00]=====
 00: player {init=5}                      enemy1 {init=3}                      enemy2 {init=1}
 01: player {dec=4}                       enemy1 {dec=2}                       enemy2 {dec=0:action_state}
 02: player {dec=3}                       enemy1 {dec=1}                       enemy2 {reset=1:ACTION:wait_state}

=====Frame[01]=====
 03: player {dec=2}                       enemy1 {dec=0:action_state}          enemy2 {dec=0:action_state}
 04: player {dec=1}                       enemy1 {reset=3:ACTION:wait_state}
 
=====Frame[02]=====
 05:                                                                           enemy2 {reset=1:ACTION:wait_state}

=====Frame[03]=====
 06: player {dec=0:action_state}          enemy1 {dec=2}                       enemy2 {dec=0:action_state}
 07: player {reset=5:ACTION:wait_state}
 
=====Frame[04]=====
 08:                                      enemy1 {dec=1}                       enemy2 {reset=1:ACTION:wait_state}

=====Frame[05]=====
 09: player {dec=4}                       enemy1 {dec=0:action_state}          enemy2 {dec=0:action_state}
 10: player {dec=3}                       enemy1 {reset=3:ACTION:wait_state}

=====Frame[06]=====
 11:                                                                           enemy2 {reset=1:ACTION:wait_state}

=====Frame[07]=====
 12: player {dec=2}                       enemy1 {dec=2}                       enemy2 {dec=0:action_state}
 13: player {dec=1}                       enemy1 {dec=1}                       enemy2 {reset=1:ACTION:wait_state}
 
=====Frame[08]=====
 14: player {dec=0:action_state}          enemy1 {dec=0:action_state}          enemy2 {dec=0:action_state}

=====Frame[09]=====
 15: player {reset=5:ACTION:wait_state}

=====Frame[10]=====
 16:                                      enemy1 {reset=3:ACTION:wait_state}

=====Frame[11]=====
 17:                                                                           enemy2 {reset=1:ACTION:wait_state}



*can be

_________________
. That's just like, your opinion, man .


Top
 Profile  
 
PostPosted: Sat Nov 17, 2018 3:45 am 
Offline
Site Admin
User avatar

Joined: Mon Sep 20, 2004 6:04 am
Posts: 3601
Location: Indianapolis
If a sprite #0 hit is needed, you could handle it near the end of the NMI routine, so it always happens. Meanwhile the processing can take as long as it needs, in the main thread. But that does limit you to putting it near the top of the screen (or else waste tons of CPU time waiting).

Quote:
I then had it execute as many turns each frame as it takes to get to the first ACTION turn for any actor. This greatly reduced the dropped input, but not completely. I'm assuming some sort of buffering would be needed. You can't buffer everything, otherwise pressing a direction would cause the player to shoot across the screen until it hit something solid. Maybe only start buffering after all buttons have been released? Maybe the entire thing is flawed. I thought about running turns until a player ACTION turn is hit, but the processing *could* take multiple frames, and would mess up the sprite0 hit.

Maybe this isn't what you're asking, but I'm not sure what you mean about buffering. We could look at something like Nethack's turn system (I don't know what it does internally, just the gameplay side). I'm thinking it's probably something like this. You'd have speed rates for every actor. Say the player's rate is 1.5, enemy #1 is 1.0, enemy #2 is 3.0

turn0:
player action
enemy #1 action
enemy #2 action
enemy #2 action
enemy #2 action

turn1:
player action
player action
enemy #1 action
enemy #2 action
enemy #2 action
enemy #2 action

and so on. game waits for input on every player action (it's kind of redefining what a "turn" is). player movement confirm would be the transition of button not pressed, to button pressed (*). the enemy movement, from the players point of view just happens all at once. enemy #2 coming towards you would appear to jump several spaces at a time. if it's next to you when your turn ends, it can attack you 3 times before your next turn. Like a familiar death in Nethack - "The leocrotta hits! The leocrotta hits! The leocrotta hits! You die..". and the player being faster than other enemies allows for the tactic such as (assuming it's always moving towards you): hit, move away, move away, hit, move away, move away, etc. and it will never touch you, only chase you. until you get cornered of course, or swarmed by other enemies.

movement speed for that could be implemented with fixed-point numbers. Add the 'rate' to your 'actor time position' on every turn. If the whole number portion of the 'time position' is non-zero, make a move, subtract 1, loop. Have the fractional portion of 'time position' preserved. then do the same for every actor.

* on second thought, this could be tricky for 8-way movement. maybe if you require any directions held for some number of frames (I imagine up+left for diagonal movement will rarely be pressed in the same exact frame). not sure if that would work well, or if any games did that. otherwise there's the indicator + move button method (like NES Genghis Khan's tactical map, NES Conflict, SNES Civilzation, I didn't like those controls very much in any of those).


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: gauauu and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group