In the last lesson, we talked about the algorithm for obtaining the moving range in SLG (the same is true for the attack Range), which is quite simple relative to the automatic path finding. Due to personal time issues, this lesson will be finished, the series will be completed, and to show examples.
Project: JavaFX Banner Game Development Example
Note: The project is an E (FX) Clipse Project
In the game development of the banner, the most basic turn logic is the enemy round and our round. Of course, in today's SLG game, is often based on our role and the role of some numerical calculation of the enemy (such as speed, etc.) to arrange the list of character manipulation, and some of the skills can also interrupt the action of a character, moving him to the back of the list of operations (such as the famous SLG game "Heroes Legend").
Of course, here we just tell the simplest round logic.
Here are some simple enumerations that we need to define:
Game state enum Status {NONE, Show_enemy_property, Show_menu, Prepare_move, MOVE, Prepare_attack, ATTACK, WAIT, Game_win, game _over}enum Gameturn {PLAYER, enemy}//current game state private status Nowstatus = status.none;//current game turn private Gameturn Nowturn = Gam Eturn.player;
We define the state of the game here. Game state is an important parameter in game development, we need to display different game interfaces according to different game states, and directly affect what the current role can do, what is going on.
Our status here contains the game state: Show enemy properties, show menu, prepare to move, move, prepare for attack, attack, wait, game win, game failed.
In addition, a turn enumeration is defined, divided into our rounds and the enemy rounds. Of course, some SLG in the camp classification more than two, such as the previous FC on the "Fourth Robot War", there is our, enemy and neutral camp (the game is called the Federation, the Union and what, forget.) This game is Alien Technology Cottage revision).
Next, the timer we created in the previous lesson will come in handy.
Movetimer = Wtimer.createwtimer (new Wtimer.ontimerlistener () {@Overridepublic void ontimerrunning (Wtimer mtimer) { if (Nowstatus = = status.move) {int nowplayerx = (int) (NOWCONTROLLPLAYER.GETX ()/tilewidth); int nowplayery = (int) (Nowco Ntrollplayer.gety ()/tileheight); if (Nowplayerx! = Movetox) {Nowcontrollplayer.movex (Nowplayerx > MoveToX?- Tilewidth:tilewidth);} else {if (nowplayery! = Movetoy) {Nowcontrollplayer.movey (Nowplayery > Movetoy?-tileheight:tileheight);} else {NowC Ontrollplayer.setwaittoattack (false); Nowcontrollplayer.setwaittomove (false); Nowcontrollplayer.setcanmove (false) ); Nowcontrollplayer = Null;nowstatus = Status.none;movetimer.stop ();}}}}); Actiotimer = Wtimer.createwtimer (new Wtimer.ontimerlistener () {@Overridepublic void ontimerrunning (Wtimer mtimer) { Enemy round if (Nowturn = = Gameturn.enemy) {if (Nowstatus = = Status.none) {//Current enemy Role Index if (Nowactionindex < Enemys.size ()) {//Select Optional Action Nowcontrollplayer = Enemys.get (nowactionindex); nowcontrollplayer.sEtchoose (TRUE);//No nearest role if (!NOWCONTROLLPLAYER.ISHASNEARBP (players)) {//If you can move if (Nowcontrollplayer.iscanmove ()) {/ /Get a recent role (you can change the rules here, such as HP lowest, etc.) Baseplayer player = NOWCONTROLLPLAYER.GETNEARESTBP (players);p ath.clear ();//Path.map _sprite = Createmapsprite ();//Search Moving range linkedlist<wnode> nodeList = path. Searchmovescan (New Point2d (Nowcontrollplayer.getx ()/Tilewidth, nowcontrollplayer.gety ()/tileheight), Nowcontrollplayer.getmove ());//delete the current movable range if there is a role, remove the move point list<wnode> deletelist = new arraylist<> (); for ( Wnode node:nodelist) {if (ispointhasplayer (int) node.getpoint (). GetX (), (int) node.getpoint (). GetY ())) { Deletelist.add (node);}} for (Wnode node:deletelist) {nodelist.remove (node);} Nowcontrollplayer.nodelist = nodelist;//Gets the closest point in the movable range from the nearest role point2d points = Player.getnearestnode (nodeList); Movetox = (int) (Point.getx ()); movetoy = (int) (point.gety ());//Status changed to move Nowstatus = Status.move;movetimer.start ();} else {//state changed to prepare attack nowstatus = Status.prepare_attack;}} else {//status changed toPrepare to attack nowstatus = Status.prepare_attack;}} else {//when the index of the action role is larger than the size of the enemy role collection, the turn ends and resets all enemy role states Nowstatus = Status.none;nowturn = Gameturn.player;nowactionindex = 0;for ( Baseplayer Enemy:enemys) {enemy.reset ();}}} else if (nowstatus = = Status.prepare_attack) {//four squares around the enemy if there is a role if (NOWCONTROLLPLAYER.ISHASNEARBP (players)) {// The enemy acquires recent our role and attacks Baseplayer BP = NOWCONTROLLPLAYER.GETNEARESTBP (players); Nowcontrollplayer.attack (BP); Nowbeattackedplayer = Bp;bp.setflash (true); nowstatus = Status.attack;} else {//No Attack object, action next enemy role Nowcontrollplayer.setcanaction (false); Nowactionindex++;nowcontrollplayer.setchoose ( FALSE); nowstatus = Status.none;}} else if (nowstatus = = Status.attack) {//Role death if (!nowbeattackedplayer.isflash ()) {if (NOWBEATTACKEDPLAYER.GETHP () <= 0 ) {Players.remove (nowbeattackedplayer);} Nowcontrollplayer.setcanaction (false); Nowactionindex++;nowcontrollplayer.setchoose (false); nowstatus = status.none;//when there is no role for us, the game ends if (players.size () = = 0) {nowstatus = Status.game_over;nowturn = Gameturn.player;}}}} else if (Nowturn = = Gameturn.player) {if (Nowstatus = = Status.attack) {if (!nowbeattackedplayer.isflash ()) {//enemy dead if ( NOWBEATTACKEDPLAYER.GETHP () <= 0) {nowcontrollplayer.getexp (Nowbeattackedplayer.getexp ()); Enemys.remove ( Nowbeattackedplayer);} Waittonextplayer ();//when there is no enemy role, the game wins if (enemys.size () = = 0) {nowstatus = Status.game_win;}}}}); Actiotimer.start ();
This section of code compares much, mainly created two timers, Movetimer and Actiontimer.
The function of Movetimer is to control the movement of a character (a cell's movement according to the time interval).
Actiontimer is the action of the enemy rounds or our rounds.
Since our rounds are mainly menu mouse events and simple judgments, here I describe the steps of the enemy rounds.
Enemy Rounds
1. The current enemy Action role index is less than the size of the enemy role list, if Canmove, get the nearest our role (also can be judged according to HP, etc.) and get the range that the enemy role can move.
2. From the moving range of the enemy role, get the closest point of "our most role from the last step" and change the status to move to start Movetimer.
3. If! Canmove (which is already moved), change the state to Prepare_attack to prepare for the attack.
4. If the status is Prepare_attack, determine whether four cells around the enemy have an object to attack, and if so, get the object and change the state to ATTACK and attack, if none, then manipulate the next enemy role.
5. If the status is attack, determine if the object being attacked is dead, and the death is removed from the linked list. When our role list is empty, the game is over.
The above is the logical step of the enemy round, the code is more comments, do not do too much explanation. Can be viewed against the project code.
Then, in mouse events and drawing, also through the state to manage, here are listed drawing code to illustrate.
public void Draw () {Gamemap.drawmap (Gcontext);d rawplayer (), switch (nowstatus) {case Show_menu:if (nowcontrollplayer! = Null && nowcontrollplayer.iscanaction ()) {Actionmenu.draw (gcontext);} Propertymenu.draw (Gcontext); Break;case SHOW_ENEMY_PROPERTY:propertyMenu.draw (Gcontext); Break;case Prepare_move: Break;case GAME_WIN:gContext.setFont (Font.font); Gcontext.setfill (Color.White); Gcontext.filltext ("Game win!", 250 , Break;case GAME_OVER:gContext.setFont (Font.font); Gcontext.setfill (color.red); Gcontext.filltext ("Game failed!" , Break;default:break); Gcontext.save (); Gcontext.setfont (font.font); switch (nowturn) {case PLAYER:gContext.setFill (color.white); Gcontext.filltext ("Our Round", getheight ()-Break;case ENEMY:gContext.setFill (color.red); Gcontext.filltext (" Enemy Rounds ", GetHeight (); Gcontext.restore ();}
In drawing, we draw different content according to different states.
The mouse event principle is the same as follows:
Event handling setonmouseclicked (E, {if (E.getbutton () = = mousebutton.primary) {switch (nowstatus) {case None:for (Baseplaye R player:players) {//Determine the clicked role, display the property box and Action menu if (Player.iscollisionwith (E.getx (), E.gety ())) {Actionmenu.setlocation ( Player.getx () + Tilewidth, player.gety ()); Actionmenu.gettextobjects () [0].setcolor (Player.iscanmove ()! = true? Color.DARKGRAY:Color.WHITE); actionmenu.gettextobjects () [1].setcolor (Player.iscanattack ()! = true? Color.DARKGRAY:Color.WHITE);p Ropertymenu.initplayer (player); nowcontrollplayer = player; Nowcontrollplayer.setchoose (true); nowstatus = Status.show_menu;}} If you click on an enemy role, only the Enemy property box for (Baseplayer Enemy:enemys) {if (Enemy.iscollisionwith (E.getx (), E.gety ())) { Propertymenu.initplayer (enemy); nowstatus = Status.show_enemy_property;}} Break;case SHOW_MENU:actionMenu.onMousePressed (e); Break;case Prepare_move:movetox = (int) (E.GETX ()/tilewidth); Movetoy = (int) (E.gety ()/tileheight); Iscanmove = false;//Determines whether the clicked is a movable range if (!ispointhasplaYer (Movetox, Movetoy)) {for (Wnode node:nowControllPlayer.nodeList) {if ((int) node.getpoint (). GetX ()) = = Movetox & & (int) node.getpoint (). GetY ()) = = Movetoy) {Iscanmove = true;}} If it can be moved, start the move timer if (iscanmove) {nowstatus = Status.move;movetimer.start (); Nowcontrollplayer.setchoose (false);}} Break;case prepare_attack://ready to attack the status, click on the role to be attacked for (Baseplayer Enemy:enemys) {if (Enemy.iscollisionwith (), E.gety ())) {Nowcontrollplayer.attack (enemy); Nowcontrollplayer.setwaittoattack (false); Enemy.setflash (true); Nowbeattackedplayer = Enemy;nowstatus = Status.attack;}} Break;default:break;}} else if (e.getbutton () = = Mousebutton.secondary) {//Right-state restore if (nowcontrollplayer! = null) {Nowcontrollplayer.setchoose ( FALSE); Nowcontrollplayer.setwaittoattack (false); Nowcontrollplayer.setwaittomove (false);} Nowstatus = Status.none;nowcontrollplayer = null;}});
Specifically, you can study the project code.
As follows:
This article is personal original, all rights reserved, reprint please indicate source:http://blog.csdn.net/ml3947. In addition to my personal blog:http://www.wjfxgame.com.
--------------------------------------------------------------------------------------------------------------- -----------------------------------------------------
In fact, this example has been done for a long time, before a csdn friend said he wanted to see examples of JavaFX banner game development. So the amateur spent a little time writing this example. Then began to write this "JavaFX Banner game development" series of blog posts, unfortunately, the middle of intermittent break from time to time to write an article, has been in the past for several months, Khan, feel oneself become a little lazy, so a total of seven lessons of the course is finished, before the series of articles have many pits, do not know when will think to fill. The second half of this year is an extraordinary six months, the examination of the driver's license, and then married, wife's house wine has been done, my home has not been done. After also prepare to buy a car, years later will be honeymoon, spare time also not much mind write that, helpless.
In addition, many friends send private messages plus QQ. But now I QQ non-special situation basically without technical discussion. After all, sometimes I want to rest or something. If you have any questions send me an email gmail:[email protected]. Thank you.
--------------------------------------------------------------------------------------------------------------
JavaFX Buff Banner game development Seventh lesson Round logic (end)