Java-Gaming.org
Play Revenge of the Titans! The situation is critical. We need fancy commanders to defend Earth, the moon, Mars!
Featured games (78)
games approved by the League of Dukes
Games in Showcase (408)
games submitted by our members
Games in WIP (293)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Roguelike turns  (Read 1345 times)
0 Members and 1 Guest are viewing this topic.
Offline RylandAlmanza

Junior Member


Medals: 3



« Posted 2012-03-12 23:51:58 »

So, I've been making a roguelike for a while, and I've just recently started thinking about the turn system. Right now, I have a very simple system. Every entity has a step() method. Every time a key is pressed, first the player's step method is called, then I loop through the enemies and npc's and call their step methods. This has worked fine so far, but it's a bit limited.

For example: Let's say we want the player to fire an arrow, and then every other entity waits until the arrow has hit something. This would not work with my system, because the enemies step right after the player steps. The other entities would step right as the arrow is fired, instead of waiting for it to hit something.

So, does anyone know of a method for timing a roguelike that is better than mine, but not too complex? Thanks!
Offline Orangy Tang

JGO Kernel


Medals: 48
Projects: 11


Monkey for a head


« Reply #1 - Posted 2012-03-13 00:04:24 »

I have all creatures return an Action that then get's processed. Only once it's done does that creature's turn finish and I begin the next one. Something like:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
interface Creature
{
  public Action takeTurn();
}

interface Action
{
  public void update();
  public boolean isFinished();
}

class Map
{
  public void update()
  {
    switch (state)
    {
      TAKE_TURN:
         action = creature.takeTurn()
      PERFORM_ACTION:
         action.update();
         if action.isFinished()
           creature = getNextCreature()
           state = TAKE_TURN
     }
  }


One of the nice things is that most of the logic goes in the action, so it can be shared between player, npc and enemies easily. Shooting an arrow would be in a ShootArrowAction, and once it's created it works the same regardless of who actually shot it.

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline sproingie
« Reply #2 - Posted 2012-03-13 00:50:01 »

I'm not sure why the firing action isn't resolved in the player's step()?  Is the arrow a separate entity?  If so, then you probably need to prioritize the arrow's step() before anyone else.  If you want to animate the arrow in steps, you should think of animation steps as separate from the simulation steps.
Games published by our own members! Check 'em out!
Play the free demo of Revenge of the Titans!
Offline KrazyTheFox

JGO Visitor




« Reply #3 - Posted 2012-03-13 15:37:44 »

I've adapted the following for use in my roguelike and am liking it quite a bit: http://roguebasin.roguelikedevelopment.org/index.php/A_simple_turn_scheduling_system_--_Python_implementation

It essentially keeps a list of which events occur on each tick. When advanceTime() is called (For example, when the player moves, he might call advanceTime(5)), it cycles through each tick and calls whatever AI or Events need updating until it reaches the new tick. Unfortunately I need to leave for class now, but this should hopefully help point you in the right direction when creating your system.

I'm sure that there's improvements to be made here, as I've only been learning Java for a couple of months now, so just remember that this is probably not as well written as it could be.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
package net.krazyweb.dungeoncrawler;

import java.util.ArrayList;
import java.util.HashMap;

import net.krazyweb.dungeoncrawler.entity.LivingEntity;
import net.krazyweb.dungeoncrawler.entity.livingentities.Player;
import net.krazyweb.dungeoncrawler.event.Event;

public class Ticker {
   
   private long ticks;
   
   private HashMap<Long, ArrayList<LivingEntity>> schedule;
   private HashMap<Long, ArrayList<Event>> eventSchedule;
   
   public Ticker(long ticks) {
      this.ticks = ticks;
      this.schedule = new HashMap<Long, ArrayList<LivingEntity>>();
      this.eventSchedule = new HashMap<Long, ArrayList<Event>>();
   }
   
   public void advanceTime(int time) {
      for (int t = 0; t < time; t++) {
         
         ticks += 1;
         
         if (schedule.containsKey(ticks)) {
            for (int e = 0; e < schedule.get(ticks).size(); e++) {
               LivingEntity entity = schedule.get(ticks).get(e);
               if (!(entity instanceof Player))
                  entity.ai.action(entity);
            }
         }

         if (eventSchedule.containsKey(ticks)) {
            for (int e = 0; e < eventSchedule.get(ticks).size(); e++) {
               Event event = eventSchedule.get(ticks).get(e);
               event.action();
            }
         }
         
      }
   }
   
   public long scheduleTurn(int interval, LivingEntity entity) {
     
      if (!schedule.containsKey(ticks + interval)) {
         schedule.put((ticks + interval), new ArrayList<LivingEntity>());
         schedule.get(ticks + interval).add(entity);
      } else {
         schedule.get(ticks + interval).add(entity);
      }
     
      return ticks + interval;
     
   }
   
   public long scheduleEvent(int interval, Event event) {
     
      if (!eventSchedule.containsKey(ticks + interval)) {
         eventSchedule.put((ticks + interval), new ArrayList<Event>());
         eventSchedule.get(ticks + interval).add(event);
      } else {
         eventSchedule.get(ticks + interval).add(event);
      }
     
      return ticks + interval;
     
   }
   
   public void unScheduleTurn(long nextMoveTick, LivingEntity entity) {
     
      if (schedule.containsKey(nextMoveTick)) {
         schedule.get(nextMoveTick).remove(entity);
      }
     
   }
   
   public void unScheduleEvent(long nextMoveTick, Event event) {
     
      if (eventSchedule.containsKey(nextMoveTick)) {
         eventSchedule.get(nextMoveTick).remove(event);
      }
     
   }
   
   public void scheduleTurnLoad(long tickToAdd, LivingEntity entity) {
     
      if (!schedule.containsKey(tickToAdd)) {
         schedule.put((tickToAdd), new ArrayList<LivingEntity>());
         schedule.get(tickToAdd).add(entity);
      } else {
         schedule.get(tickToAdd).add(entity);
      }
     
   }
   
   public long getTicks() {
      return ticks;
   }
   
}
Offline Archibald

Junior Member


Projects: 1



« Reply #4 - Posted 2012-03-13 20:39:42 »

You don't put missiles in the same system as player/monster turns in roguelikes (althrough it would be logical if you were making RPG). Missiles are instant things, these are part of display system, not game logic system. Players/monsters do their things. When one of the actions is fire a missile, you stop the execution of player turns (actually you don't have to stop anything since roguelikes are turn based) and display animation of missile moving around. When all animations are finished the player is allowed to press next button.

Also note that things will get hairy if you have various speed of monsters. In such case the typical solution is to move the entity (monster/player) with the highest remaining speed, when none of the entites have enough speed to move the speed is replenished by the base speed.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

Play Revenge of the Titans! The situation is critical. We need fancy commanders to defend Earth, the moon, Mars!
 
Browse for soundtracks for your game!

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

The invasion has landed! On Mars! And you're there to beat 'em!
cubemaster21 (130 views)
2013-05-17 21:29:12

alaslipknot (138 views)
2013-05-16 21:24:48

gouessej (168 views)
2013-05-16 00:53:38

gouessej (160 views)
2013-05-16 00:17:58

theagentd (172 views)
2013-05-15 15:01:13

theagentd (157 views)
2013-05-15 15:00:54

StreetDoggy (201 views)
2013-05-14 15:56:26

kutucuk (225 views)
2013-05-12 17:10:36

kutucuk (224 views)
2013-05-12 15:36:09

UnluckyDevil (228 views)
2013-05-12 05:09:57
Complex number cookbook
by Roquen
2013-04-24 12:47:31

2D Dynamic Lighting
by Oskuro
2013-04-17 16:46:12

2D Dynamic Lighting
by Oskuro
2013-04-17 16:45:57

2D Dynamic Lighting
by Oskuro
2013-04-17 16:23:20

Noise (bandpassed white)
by Roquen
2013-04-05 17:36:01

Noise (bandpassed white)
by Roquen
2013-04-03 16:17:38

Java Data structures
by Roquen
2013-03-29 13:21:12

Topic Request
by kutucuk
2013-03-22 21:42:01
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!
Page created in 0.119 seconds with 21 queries.