Show Posts
|
|
Pages: [1] 2
|
|
1
|
Developer / Technical / Can I get someone to check my game code's architecture?
|
on: July 15, 2013, 02:39:43 PM
|
So I'm in the middle of this pet project and as I'm still a novice I have hit a theoretical wall. The project can be found at github. It's a versus board game, some sort of dev diary can be found here. There are two problems right now: I feel the state machine is very crappily implemented and every small change makes a huge ripple effect. The second one is something that's not already there, my game loads skill behavior from a script that has access to an API, but I don't know how to implement it in a coherent way to allow skill interaction (eg. a "slow target creature" skill makes all other skills that imply movement reduce their range). I don't know if someone would be up for serious mentoring in this matter but I'd be heavily interested as it's part of my job but you can self-teach so far. The game is written using Artemis, so the core pattern is composition. Assume we're using com.wartricks namespace. The graphical stuff is nonimportant here so I'll focus on the game matters. Libgdx runs in a loop that calls lifecycle.BoardScene.render() every time it's available, with a delta time. Boardscene holds an instance of logic.VersusGame, which is where most of the game code is. Refer to this gif to get an idea of the current gameplay: http://i.imgur.com/P2ImIQe.gif------------------------------------------------------------------------- **Game Logic**logic.VersusGame has an input multiplexer, and a logic.StateMachine. StateMachine is an observable composed of some ints to indicate current active creature, skill and hex target and a State (enum) CHOOSING_CHARACTER, CHOOSING_SKILL, CHOOSING_TARGET, CHOOSING_CONFIRM, PLAYER_FINISHED, BEGIN_TURN, END_TURN Whenever the state changes VersusGame gets the callback at update() and changes the game screen accordingly. For every state there's an associated method. Input is taken from either one of the inputsystems at namespace input, or the UI controls handled by the Stage reference in VersusGame. They get menu or boardgame clicks and change the state and selected creatures/skills accordingly. The way input multiplexing works in libgdx is that inputsystems will be called one by one until one of them returns true, so most of them check for current game state first. ------------------------------------------------------------------------- **As for the scripting of characters and skills**Here is where Artemis comes in full effect. Every creature and skill is an Entity formed of several components. A basic creature has an HP and energy regeneration value, plus several skills identified by their names. A skill is composed of a cooldown, range, cost and initiative. The game has an ActionExecutor that calls any method inside a script with any number of parameters. The way it works, every script has its own instance of the interpreter with game being passed as a global value. Game is an instance of logic.Api and contains all methods scripters have available. At the beginning of the game in logic.VersusGame.startLogic() some creatures are created by calling their names. The current creatures are hardcoded in line 164. For every creature there is a BeanShell script at wartricks-android\assets\scripts\characters\ as name.bsh Sample creature "Female": create() { name = "Female"; health = 100; energyPerTurn = 4; skillSet = new Array(); skillSet.add("move"); skillSet.add("push"); creatureId = game.createCreature(name, health, energyPerTurn, skillSet); return creatureId; } Name is used to get the sprite associated for that creature. For every skill in their skillset logic.Api.createCreature() calls createSkill() which spawns a new Entity and tags it. For every creature there is a BeanShell script at wartricks-android\assets\scripts\skills\ as name.bsh Sample skill "push", moves all creatures in a cone one hex away from the caster: int skillId = -1; Array affected; create() { name = "push"; cost = 2; minRange = 1; maxRange = 1; initiative = 600; cooldown = 0; skillId = game.createSkill(name, cost, minRange, maxRange, initiative, cooldown); return skillId; } affected() { affected = game.skillGetHexesForArea(Shapes.CONE, 0, 2, origin.x, origin.y, target.x, target.y); return affected; } execute() { creatures = game.skillGetCreaturesInPositionArray(affected); pushDirection = game.skillGetDirection(origin.x, origin.y, target.x, target.y); for (int i = 0; i < creatures.size; i++){ game.creatureMoveBy(creatures.get(i), pushDirection.x, pushDirection.y); } return true; }
onBeginTurn() { }
onEndTurn() { } create() is called on creation. affected() is called in the CHOOSING_TARGET step by input.TargetSelectInput.touchUp() to determine the affected tiles given that my engine supports several AoE shapes. execute() is called on turn resolution by onPlayerFinished(). Now the scripts allow for OnBeginTurn, OnEndTurn actions. There are two systems -system.OnBeginTurnExecute and system.OnEndTurnExecute- that are called at the beginning and end of each turn by logic.VersusGame.onBegin/EndTurn(), and will execute onBeginTurn() and onEndTurn() methods for a given script if that skill has a component OnBegin or OnEnd. There's no API support to add OnBegin and OnEnd to an entity yet but it was tested in previous versions and it works.
|
|
|
|
|
5
|
Community / DevLogs / Re: Wartricks - arena tactics with tasty hexagons
|
on: June 18, 2013, 01:18:38 PM
|
First draft of modding API available. Example: http://i.imgur.com/as8DwNJ.gifNew format for scripts, more user friendly and doesn't require internal knowledge of the application, just the available documented API methods (that I can increase on demand). Creature int creatureId = -1;
// CREATES THE CREATURE WITH CUSTOM VALUES create() { name = "apple"; health = 100; energyPerTurn = 3; skillSet = new Array(); skillSet.add("move"); creatureId = game.createCreature(name, health, energyPerTurn, skillSet); return creatureId; }
Skill int skillId = -1;
Array affected;
// CREATES THE SKILL WITH OWN VALUES create() { name = "move"; cost = 1; minRange = 1; maxRange = 2; initiative = 600; cooldown = 0; skillId = game.createSkill(name, cost, minRange, maxRange, initiative, cooldown); return skillId; }
// SHOWS THE AFFECTED HEXES affected() { affected = game.skillGetHexesForArea(Shapes.CIRCLE, 0, 0, origin.x, origin.y, target.x, target.y); return affected; } // INSERT SKILL EFFECT HERE execute() { return game.creatureMoveTo(caster, target.x, target.y); }
// BEGIN AND END OF TURN EFFECTS HERE // ACTIVABLE WITH game.skillActivateBeginTurn() OnBeginTurn() { }
OnEndTurn() { }
|
|
|
|
|
7
|
Community / DevLogs / Re: Wartricks - arena tactics with tasty hexagons
|
on: June 17, 2013, 06:08:25 AM
|
|
TO DO LIST
UI Add buttons for undo. // DONE BUT UNUSED BECAUSE IT'S ONE MOVE PER CREATURE ATM
TURN SEQUENCE Allow undo. // DONE BUT UNUSED BECAUSE IT'S ONE MOVE PER CREATURE ATM Allow multiple actions to be queued per creature. Make the whole projectiles logic.
MOD API Start scripting my own skills to see which methods could be needed. Get someone to script more skills and add methods to the API on demand.
Graphics Make UI decent to look at. Add hex types for flavor.
Skills Allow adding enhancements.
Many other things I cannot remember now
|
|
|
|
|
8
|
Community / DevLogs / Re: Wartricks - arena tactics with tasti hexagons
|
on: June 17, 2013, 05:59:31 AM
|
|
RULESET
DISCLAIMER: All numeric values are provisional for any part of the game. This is just one iteration of several that have happened before and will after. The game is played on a rectangular board with a to be decided size. Right now I'm leaning towards 10x7, with hexes having flat side up. Every player gets to choose 3-5 character from a roster. Every creature has a life value, gauge regen value and a set of 3-5 skills. Movement is considered a standard skill. We have a new per-player stat: gauge meter (or energy, or pills, or mana, or action points, it's just a number). Every character adds an amount of gauge to the meter at the beginning of the turn. Maybe the gauge already has a base value when the game starts. Turn sequence: - Each character adds its gauge regen value to the pool. - Each character gets 2 personal temporary gauges. - The players choose secretly which skills to play for every character. The cost can be taken from the temporary and the meter. A creature can have any number of extra actions per turn at the cost +1 for the 2nd, +2 for the 3rd, +3 for the 4th, etc... - Once the planning is done, actions are resolved respecting initiative, in steps. All characters resolve their first skill, then all creatures resolve the second skill and the third or fourth if they paid for them. - Some skills put projectiles on the board. Projectiles like arrows or fireballs are considered of initiative 0 so they are moved at the beginning of every *step*. - In case of "collision" (several characters trying to enter the same hex or similar), the highest initiative gets to do the action. Both players spend their gauges and their skills are put on cooldown, but the loser cannot take more actions this turn and loses any other gauges he has spent for further actions. Any other actions he could have done are not put on cooldown. - At the end of the turn, all unspent temporary gauges are taken away. Extras: - Extra gauge can be paid to increase/decrease initiative by an amount. - Extra gauge can be paid for any skill for extra effects, if the description says so (i.e. extra range, extra duration, extra damage, in-action delay)
|
|
|
|
|
9
|
Community / DevLogs / Wartricks - arena tactics with tasty hexagons (NO MORE PONIES)
|
on: June 17, 2013, 05:53:24 AM
|
Hi Tigsource! I'm developing a pet project in my spare time that I think fills a niche that's overlooked. The idea is to make a skill-centric arena game trying to emulate what would be a PvP experience between two D&D parties. It has been done on boardgames before ( Mage Wars, Summoner Wars) but I want a version with automation, mods and other videogame goodies. I'm developing in libgdx and testing on Windows and Android. A mod API to add your skills is already in development so you can write your own characters/skills. Here's some info about the game:  General info Genre: Turn-based tactics Platform: PC & Android (iOS/Mac/Web potentially) Target group: RPG, Tactics, TCG, Dota and fighting game players. Rating: Teen? # of Players: 2+  Features  • Pick your character lineup from our character roster • Battle your friends in local with just one phone • Board any size you want! • Mod in own characters and their skills • Look at the code and laugh at my noobishness  Repository: https://github.com/pakoito/WartricksProject
|
|
|
|
|
10
|
Jobs / Collaborations / Hex tactics with skill-centric combat - Playtesting with proxies
|
on: June 09, 2013, 05:51:25 AM
|
I am iterating over my game design while I keep developing the engine for my pet project. The code is almost up to the point where gameplay has to be implemented, but my design is lagging behind a bit. I need someone to play with online, or that would be able to play with a friend and proxies. About my game, it's hex tactical skirmishes in a small board, 3 characters per side and skill-centric combat. It leans more towards D&D4 than Fire Emblem. It can be played online using a vassal-engine module as a proxy. A copy of the rules with some examples can be found in this link.
|
|
|
|
|
11
|
Developer / Technical / Line of sight on “even-q” vertical flat topped hex grid
|
on: June 09, 2013, 12:32:30 AM
|
LINKS TO PAGES AND IMAGES AT THE END OF THE TEXT.Reference image:  What I want is an algorithm that given hex A and hex B returns all hexes that would be crossed by a line going from the center of A to the center of B, and in case of diagonal going right through a division it selects both sides of it. As in A(0,1) and B(2,1) => {[0,1][1,1][1,0][2,1]} for horizontal and A(1,0) B(0,2) => {[1,0][0,1][1,1][0,2]} for diagonal. An in-game example: character in A(0,1) shoots arrow towards B(6,1) the arrow will check for collision in Step 1: [1,1][1,0], Step 2: [2,1], Step 3: [3,1][3,0], Step 4: [4,1], Step5: [5,1][5,0], Step 6: [6,1] I'm trying to implement a Line Draw or Line of Sight algorithm for my hex boardgame. Upon reading several different solutions from most common places like the [Hex Bible][1] none of the algorithms adapted to my grid config (even-q as stated in Hex Bible). After a sleepless night I have come up with 3 different solutions: two adapted and one of my own. None of them gives perfect results because the math is flawed, so I would like some help. All 3 solutions can be found and tested by downloading [my git project][2]. The class is found at com.wartricks.tools.MapTools.java Algorithm 1 as per hex bible: public Array<Pair> getLOSCells(int x, int y, int x0, int y0) { final Array<Pair> highlights = new Array<Pair>(); // PROBLEM! my offset system has 0,0 on the bottom left and is flat-top // coord2Offset gives valid results, but they don't translate well // for example my 0,1 should be 0,1,-1 but gets 0,-1,1 instead // this causes problems with rounding that make the line break final int[] cubeCoordsOrigin = MapTools.coordOffset2Cube(x, y); final int[] cubeCoordsDestination = MapTools.coordOffset2Cube(x0, y0); final int dx = cubeCoordsOrigin[0] - cubeCoordsDestination[0]; final int dy = cubeCoordsOrigin[1] - cubeCoordsDestination[1]; final int dz = cubeCoordsOrigin[2] - cubeCoordsDestination[2]; float distance = Math.max(Math.abs(dx - dy), Math.abs(dy - dz)); distance = Math.max(distance, Math.abs(dz - dx)); if (distance > 0) { int[] previousCoord = new int[3]; for (float i = 0; i <= distance; i++) { final float currentX = (cubeCoordsOrigin[0] * (i / distance)) + (cubeCoordsDestination[0] * (1 - (i / distance))); final float currentY = (cubeCoordsOrigin[1] * (i / distance)) + (cubeCoordsDestination[1] * (1 - (i / distance))); final float currentZ = (cubeCoordsOrigin[2] * (i / distance)) + (cubeCoordsDestination[2] * (1 - (i / distance))); final int[] currentCoord = roundCubeCoord(currentX, currentY, currentZ); if (!currentCoord.equals(previousCoord)) { final int[] offsetCoord = MapTools.coordCube2Offset(currentCoord[0], currentCoord[1], currentCoord[2]); highlights.add(new Pair(offsetCoord[0], offsetCoord[1])); previousCoord = currentCoord; } } } return highlights; }
public static int[] coordOffset2Cube(int x, int y) { final int[] coord = new int[3]; coord[0] = x; coord[2] = y - ((x + (x % 2)) / 2); coord[1] = -x - coord[2]; return coord; }
public static int[] coordCube2Offset(int x, int y, int z) { final int[] coord = new int[2]; coord[0] = x; coord[1] = (z + ((x + (x % 2)) / 2)); return coord; }
public static int[] roundCubeCoord(double x, double y, double z) { float rx = Math.round(x); float ry = Math.round(y); float rz = Math.round(z); final int s = (int)(rx + ry + rz); if (s != 0) { final float x_err = (float)Math.abs(rx - x); final float y_err = (float)Math.abs(ry - y); final float z_err = (float)Math.abs(rz - z); if ((x_err > y_err) && (x_err > z_err)) { rx -= s; } else if (y_err > z_err) { ry -= s; } else { rz -= s; } } return new int[] { (int)rx, (int)ry, (int)rz }; } this one is a mess, it doesn't behave as expected at all ![errors 1][3] Algorithm B as per Bresenham's Line Draw: public Array<Pair> getLOSCellsPlanB(int y1, int x1, int y2, int x2) { // Works with errors, probably due to being swapped with x and y // !!!Designed for even-r pointy-tops final Array<Pair> highlights = new Array<Pair>(); int i; // loop counter int ystep, xstep; // the step on y and x axis int error; // the error accumulated during the increment int errorprev; // *vision the previous value of the error variable int y = y1, x = x1; // the line points int ddy, ddx; // compulsory variables: the double values of dy and dx int dx = x2 - x1; int dy = y2 - y1; highlights.add(new Pair(y1, x1)); // first point // NB the last point can't be here, because of its previous point (which has to be verified) if (dy < 0) { ystep = -1; dy = -dy; } else { ystep = 1; } if (dx < 0) { xstep = -1; dx = -dx; } else { xstep = 1; } ddy = 2 * dy; // work with double values for full precision ddx = 2 * dx; if (ddx >= ddy) { // first octant (0 <= slope <= 1) // compulsory initialization (even for errorprev, needed when dx==dy) errorprev = error = dx; // start in the middle of the square for (i = 0; i < dx; i++) { // do not use the first point (already done) x += xstep; error += ddy; if (error > ddx) { // increment y if AFTER the middle ( > ) y += ystep; error -= ddx; // three cases (octant == right->right-top for directions below): if ((error + errorprev) < ddx) { highlights.add(new Pair(y - ystep, x)); } else if ((error + errorprev) > ddx) { highlights.add(new Pair(y, x - xstep)); } else { // corner: bottom and left squares also highlights.add(new Pair(y - ystep, x)); highlights.add(new Pair(y, x - xstep)); } } highlights.add(new Pair(y, x)); errorprev = error; } } else { // the same as above errorprev = error = dy; for (i = 0; i < dy; i++) { y += ystep; error += ddx; if (error > ddy) { x += xstep; error -= ddy; if ((error + errorprev) < ddy) { highlights.add(new Pair(y, x - xstep)); } else if ((error + errorprev) > ddy) { highlights.add(new Pair(y - ystep, x)); } else { highlights.add(new Pair(y, x - xstep)); highlights.add(new Pair(y - ystep, x)); } } highlights.add(new Pair(y, x)); errorprev = error; } } // assert ((y == y2) && (x == x2)); // the last point (y2,x2) has to be the same with the // last point of the algorithm return highlights; } the problem with 2 is that it adds extra squares where it shouldn't because it's calculating for pointy-top hexes ![errors 2][4] Algorithm 3 as I like it. It uses some magic numbers because of some offsets in the render system. public Array<Pair> getLOSCellsPlanC(int x1, int y1, int x2, int y2) { final Array<Pair> highlights = new Array<Pair>(); final int dx = x2 - x1; final int dy = y2 - y1; final FloatPair origin = this.world2window(x1, y1); final FloatPair destination = this.world2window(x2, y2); final float dpx = destination.x - origin.x; final float dpy = destination.y - origin.y; final float distance = 2 * Math.max(Math.abs(dx), Math.abs(dy)); if (distance > 0) { for (int i = 0; i <= distance; i++) { final float currentX = ((origin.x + ((dpx * i) / distance))); final float currentY = ((origin.y + ((dpy * i) / distance))); float posx = ((currentX) / gameMap.colSize); float posy = (((currentY) - ((gameMap.rowSize * (posx % 2)) / 2)) / gameMap.rowSize); final Pair targetHex = new Pair((int)posx, (int)posy); highlights.add(targetHex); } } return highlights; } results from A3 ![Algorithm 3][5] errors from a3: jumps and inconsistent move ambiguities, only 1 diagonal behaves the way I want. ![Errors 3][6] [1]: http://www.redblobgames.com/grids/hexagons [2]: https://github.com/pakoito/WartricksProject [3]: http://i.stack.imgur.com/4Oc5G.gif [4]: http://i.stack.imgur.com/J2fnD.gif [5]: http://i.stack.imgur.com/S7GgM.gif [6]: http://i.stack.imgur.com/2IRVm.gif
|
|
|
|
|
13
|
Developer / Design / Re: Simultaneous turns on tactics game
|
on: May 29, 2013, 09:34:50 AM
|
whoah, I've been working on the exact same type of game. simultaneous tactics game.
I couldn't work on it for some days but I made some changes yet I'm still not convinced. How about you?
|
|
|
|
|
15
|
Developer / Design / Re: Simultaneous turns on tactics game
|
on: May 24, 2013, 04:09:12 AM
|
|
I was experimenting for a while and came up with another completely new system based on the waging gimmicks. I think it can also keep it multi-turn and deal with collision.
We have a new per-player stat: gauge meter (or coins, or pills, or mana, it's just a number). Every character adds an amount of gauge to the meter at the beginning of the turn. Maybe the gauge already has a base value when the game starts.
Now, the actions available (with arbitrary costs) - Move: costs 2 gauges. - Spell/skill: costs X gauges. - Counter: special skill.
Turn sequence: - Each character adds its gauge regen value to the pool. - Each character gets 2 personal temporary gauges. - The player chooses an action for every character. The cost can be taken from the temporary and the meter. - If the player wants, he can spend gauges from the global meter to make its toons do extra actions. - Actions are resolved simultaneously, but respecting initiatives. Missiles like arrows or spells are considered of initiative 0 so they are moved at the beginning of the action. - In case of collision or counter, the highest bidder gets to do the action. In case of draw in the bids, initiative wins. Both players spend their gauges and their skills are put on cooldown, but the loser cannot take more actions this turn and loses any other gauges he has spent for further actions. Any other actions he could have done are not put on cooldown. - At the end of the turn, all unspent temporary gauges are taken away.
Extras: - Extra gauge can be paid for unsafe skills to avoid being countered. - Extra gauge can be paid for any skill for extra effects, if the description says so (i.e. extra range, extra duration, extra damage, in-action delay)
Action examples (arbitrary numbers): Move Cost 2 Range 1 Initiative Depends on char, range 500-600. Cooldown 0 Unsafe False Movespeed Instant Type Physical Effect: Moves character one hex Enhances: 1 gauge for +500 initiative delay, 1 gauge -20 initiative delay
Fireball Cost 3 Range 1-4 Initiative 345 Cooldown 2 Unsafe True Movespeed 2 Type Magic Effect: 3 damages in radius 1 from target. Explodes if enters an occupied hex. Enhances: 1 gauge for +500 initiative delay, 1 gauge for max range +1, 2 gauges for damage +1
Grappling hook Cost 4 Range 2-3 Initiative 435 Cooldown 8 Unsafe True Movespeed Instant Type Physical Effect: Moves enemy to your adjacent hex. Cancel the rest of his actions this turn. Enhances: 1 gauge for +500 initiative delay, 3 gauge for max range +1
Swing Cost 2 Range 1 Initiative 820 Cooldown 0 Unsafe False Movespeed Instant Type Physical Effect: Deals 2 damage to all enemies in arc Enhances: 2 gauge for -300 initiative speedup, 3 gauge for +1 damage
Arrow Cost 2 Range 10 Initiative 830 Cooldown 1 Unsafe False Movespeed 1 Type Physical Effect: Deals 2 damage the first enemy it crosses with Enhances: 2 gauge for -500 initiative speedup, 3 gauge for +1 damage
Break Concentration Cost N Range 1 (Swordman), 1-2 (Spearman), 2-3 (Archer) Initiative 10 Cooldown 0 Unsafe False Movespeed Instant Type Counter Effect: Stops any unsafe actions done within range with cost N*1.5 rounded down until the end of turn. Enhancements do not count towards cost.
Counterspell Cost N Range 1-5 Initiative 11 Cooldown 2 Unsafe False Movespeed Instant Type Counter Effect: Stops the next unsafe magic actions done within range with cost N until the end of turn. Enhancements do not count towards cost. Enhace: Pay M to stop M additional unsafe magic actions.
|
|
|
|
|
16
|
Developer / Design / Re: Simultaneous turns on tactics game
|
on: May 23, 2013, 10:01:25 AM
|
|
I think I have it. 2+ creatures can be in the same square. Make skills have an "interruptible" and "causes clash" properties. Movement causes clash but is never interruptible.
Following initiative every char resolves its action, and if in threat range of any enemy a clash is resolved (RPS or whatever system) with a winner, damage is applied, and if the active char loses and was doing an interruptible action, it won't. There will be a new engagement when the other toon(s) in the hex take their actions, if those actions are marked as "cause clash".
This solves the following problems: Threat range: different toons can affect more "causes clash" actions done around them, Fighter classes can interrupt spells, and turn sequence is never broken. It also melds quite well with the action initiative system.
For a bit of mindgames but not a lot of molesting problems, a 3-action turn should suffice.
EDIT: And maybe an extra mandatory clash at the beginning of every action to encourage mages not to stay in place and warriors do.
|
|
|
|
|
17
|
Developer / Design / Re: Simultaneous turns on tactics game
|
on: May 23, 2013, 09:29:31 AM
|
If the game is async like a mobile game with push notifications, and your always waiting for turns anyways, I don't see the point in simultaneous turns.
It's simultaneous in a per-turn basis, but every turn would be ruled by skill/move initiatives. The alternatives to simultaneous are full team alternate turns (Hero Academy) or per-character turns (Chess). They are completely different games that completely trump the timing/mindgames mechanic, and I don't want that.
|
|
|
|
|
18
|
Developer / Design / Re: Simultaneous turns on tactics game
|
on: May 23, 2013, 09:15:56 AM
|
|
There is a problem with the movement initiative system. Imagine this sequence.
P1: Move 10,10 Skill Fireball 6,6 Skill Buff Move 10,11 Skill Attack
P2: Move 10,10 Move 11,10 Move 12,10 Skill Ranged Skill Trap
Let's say P1 wins initiative, or RPS, or whatever system. P2 either gets the rest of its curn canceled or its next move delayed by one turn. The first case is directly imbalanced, and in the second case poses more problems as the next turn he'll try to get in while the other player is staying there. If he loses it's the same as the first case as he'll keep losing until the other player leaves the hex, but if he wins the other player will have his sequence altered and rollback not only one but two turns or it'll directly break his whole sequence.
|
|
|
|
|
19
|
Developer / Design / Simultaneous turns on tactics game
|
on: May 23, 2013, 07:39:19 AM
|
|
Hi TIG, I'm finished with the tool testing phase (libgdx+Artemis+Lua), shit moves, animates and responds to user input. Off to the gamebuilding phase.
Here's my idea: Fantasy tactics game, K'sB/HOMM/Eador board-type, with the twist of simultaneous turns like Frozen Synapse. The game must be completely asynchronous.
Each player gets 3-5 toons, and has to declare turns of 5 actions for every toon. Actions include moving one hex, skills and ranged attacks. Once the turn is completed and resolved, both players get a new one.
Sample skills: Charge, Fireball, Acid Trap, Magic Missile, Counterspell, Grappling Hook...
Now, off to the problems:
Projectiles: a creature shoots an arrow/fireball. There's two approaches here. One is the most common, you choose a target hex, the effect is triggered, on to the next turn. The second approach would be making some spells put a token on the board symbolizing the projectile arriving to its destination so it can be dodged. A spell will include its movespeed.
Given the simultaneous turn approach I feel the inclusion of the second approach worthwhile to emphasize mobility and zoning tactics. Besides, it forces timing into some spells trying to outsmart the opponent about on which turn you will fire it, and in which direction.
Collision: two toons decide to move to the same hex. This one is the most problematic. I thought of an "engaged" state, same as in D&D. If two creatures enter within each other's threat area, their actions are substituted by a rock-paper-scissors(-lizard-spock) system. Creatures have a previously declared "stance" on the RPS(Ls) set and will do that action until the engagement is broken somehow. A implementation of the RPS system would be attack beats flee beats special. Attack is self-explanatory, Flee is a backstep, Special would be a per-character skill to balance the engagement, i.e. wizard-types would get telekinetic push while warriors get grapple.
The problem are two: first, the creature would carry on with its stance during the whole engagement, and it may be a losing or just a support/nondamagic one. Second, if the engagement is broken by one of the creatures escaping its 5-turn sequence is broken and it may not be able to carry on the rest of the actions.
Threat areas: marksman, a creature of size big or wearing a spear may have a bigger threat range. I thought about giving them a skill in the fashion of "ready action", where they get a threat area and anything that moves in it gets one attack.
Initiative: what is resolved first? This one is easy, same as in Yomi or Space Hulk Death Angel, each skill/attack is coded with an initiative number either unique or very specific to avoid draws. In case of draw, randomness is applied.
What is your opinion and how would you improve it?
|
|
|
|
|
20
|
Developer / Technical / Re: Need intermediate engine/framework advice
|
on: May 04, 2013, 10:23:37 AM
|
For cardgames like Magic or similar (way more complex that my game, but a common example) scripting is the way to go. As a server developer for Magic Online, I can assure you that we don't do it that way. I don't think I'm allowed to tell you how it's done, but it's not that. Completely understandable, you are a company with a big name and senior engineers and everything, but I cannot fathom the answer myself, so I was working under the asumption I had already seen in other's code, like Magarena. https://code.google.com/p/magarena/wiki/ImplementingCardsAs you see, they have file parsing for simple cards with common abilities, and in case extra code is needed they use Groovy as their scripting language. EDIT: I have found an architecture tip using a command-pattern, but it needs recompilation and redeployment anyway. It still works with scripted cards, so I'm probably base my architecture around that.
|
|
|
|
|