国外做ppt的网站有哪些,网站流量能打开wifi打不开,产品画册,河南省住房城乡和建设厅网站首页介绍 Ť他是与一个六个部分组成的系列的第3部分的JavaFX 2游戏教程。 如果您错过了第1部分和第2部分 #xff0c;建议您在开始本教程之前先进行阅读。 回顾第二部分#xff0c;我讨论了游戏循环的内部工作原理#xff0c;其中我们使用动画#xff08;JavaFX Timeline … 介绍 Ť他是与一个六个部分组成的系列的第3部分的JavaFX 2游戏教程。 如果您错过了第1部分和第2部分 建议您在开始本教程之前先进行阅读。 回顾第二部分我讨论了游戏循环的内部工作原理其中我们使用动画JavaFX Timeline 更新精灵检查碰撞并清理游戏世界元素然后我不得不创建一个简单的游戏引擎以简化操作开发2D游戏。 本教程是关于使用游戏引擎并使用鼠标和键盘来演示输入的。在本教程中我将为您提供一些背景历史记录事件处理基础知识演示游戏以及最后的实现。 该演示将展示一艘能够在漂浮的球体上射击的飞船类似于电子游戏“ 小行星” 。 如果要运行演示请向下滚动并单击下面的WebStart按钮。 在启动游戏之前请先阅读要求。 历史 在上世纪80年代那年小时候这里有拱廊中心保龄球馆披萨店和7家11家商店我花了大量时间在玻璃展示区摆放着四分之一的空间以便与玻璃陈列室相邻。目前正在玩激烈的电子游戏的家伙。 当每个人都拥挤在他身边时看着他击败了所有的最高分当我们看到伟大时我们所有人都为之欢呼。 其中的一个令人难以置信的真棒街机游戏是“ 小行星 ”由Atari公司创建打参观play.vg 说到高分并不是很多人都知道但是斯科特·赛峰 Scott Safran 1967年2月3日至1989年3月27日是有史以来玩小行星的最高记录。 他在当地的7-11便利店里连续玩了大约二十个小时才做到了这一点。 在生命的后期还很小的时候他在1989年3月27日的一次不幸事故中去世。为了纪念Scott我创建了本教程。 我希望人们会记得他是有史以来最伟大的视频游戏玩家之一我敢肯定他也是个好兄弟。 关于游戏小行星基于矢量的硬件用于渲染形状而不是栅格图形位图。 另外使用光栅图形创建了Midway Inc.的Space Invaders。 令人兴奋的是有关于JavaFX 2.x能够使用称为JavaFX Canvas Node的位图的讨论该位图可以提供栅格图形以使开发人员能够利用像素级操纵。 这些街机风格的机柜的结构仍然让我感到惊讶这些机柜内装有CRT主板和诸如按钮操纵杆跟踪球和旋钮之类的控制器输入设备。 经典街机游戏 以下是一些具有多种输入设备的经典街机游戏 仅按钮 小行星太空侵略者翻录凤凰 仅操纵杆 Q * bertPacMan 仅旋钮 Pong 仅轨迹球 大理石疯狂 操纵杆和按钮 星球大战 杆位间谍猎人 自行车车把 特技自行车纸男孩 按钮和油门杆 月球着陆器 潜望镜和按钮 海狼 按钮和轭 Tron战区 按钮旋钮和拨叉 《星际迷航》《暴风雨》 按钮和轨迹球 导弹司令部enti 按钮和操纵杆 防御者护手蛙人乔斯特狂风马里奥兄弟金刚西捷加拉加功夫魂斗罗街头霸王双龙忍者魔法或精神挖土龙之巢穴。 输入/鼠标键盘 抛开过去我们目前遇到了新型的输入设备例如触摸屏加速度计红外接收器照相机等。当今台式机上最常见的输入是鼠标和键盘。 当然触摸屏已广泛应用于移动设备和平板电脑但是在本教程中我们将仅着眼于“ 鼠标 ”和“ 键盘 ”作为控制游戏的输入。 基于JavaFX路线图 正在进行多点触摸输入 在您阅读本文时它已经实现了。 侦听键盘和鼠标事件时JavaFX 2.x具有许多类型的事件这为开发人员提供了机会来实现侦听触发事件的事件处理程序。 用于节点或场景的JavaFX 2.x API包含许多带有前缀“ on”的方法例如onMousePressProperty或onKeyPressProperty方法。 无论何时实现这些方法都将使用Java的泛型类型简单地实现handle方法以指定要传递给查询的事件对象。 因此当实例化EventHandler MouseEvent类时将实现一个handle方法该方法将MouseEvent作为要传入的参数。 下面显示的代码段将两个事件处理程序添加到JavaFX Scene。 第一个处理程序将响应鼠标事件。 在我们的简单游戏中当发生鼠标按下时该处理程序将通过发射武器或在飞船上进行响应。 下面显示的第二个处理程序将响应按键事件。 当按下一个键时此处理程序将处理KeyEvent对象。 在我们的游戏中按键“ 2 ”会将您的辅助武器变成更大的冲击波更慢。 其他任何击键将默认返回到较小的冲击波更快。 移动船和火武器 EventHandler fireOrMove new EventHandlerMouseEvent() {Overridepublic void handle(MouseEvent event) {if (event.getButton() MouseButton.PRIMARY) {// Fire weapon systems. On Windows left mouse button} else if (event.getButton() MouseButton.SECONDARY) {// Navigate ship thrust. On Windows right mouse button}}};primaryStage.getScene().setOnMousePressed(fireOrMove); 更换武器 EventHandler changeWeapons new EventHandlerKeyEvent() {Overridepublic void handle(KeyEvent event) {myShip.changeWeapon(event.getCode());}};primaryStage.getScene().setOnKeyPressed(changeWeapons); JavaFX 2输入演示–“扩展” 简单的演示游戏将是《星际争霸》和《小行星》之间的混合体。 使用鼠标导航飞船时它将类似于《星际争霸》的《 战舰巡洋舰》 。 如果您还记得本系列文章的第2部分那么我创建了球体反弹。 我重用了第2部分“原子粉碎机”中的代码像著名的街机游戏一样充当小行星。 除了在这个游戏中您根本不会受到伤害。 目的是在您的武器撞到撞击后会爆裂的其他球体之前向它们发射武器。 由于这是一个简单的教程甚至是处于开发初期的游戏因此该游戏无法跟踪得分。 我鼓励您去GitHub下载代码并增强游戏。 稍后您将看到一个高级UML类图该图描述了组成游戏的类。 为了简洁起见我不会详细介绍每个类但是我相信您会在这里访问GitHub https //github.com/carldea/JFXGen以获取所有演示和源代码。 要求 Java 7或更高版本 JavaFX 2.1或更高版本 Windows XP或更高版本应该很快可用于Linux / MacOS 一个简单的小行星类型游戏名为“ The Expanse”。 说明 右键单击在Windows上以飞船。 单击鼠标左键在Windows鼠标上单击鼠标左键即可射击武器。 按键2 变成大型导弹。蓝色圆形弹丸 其他按键默认为较小的导弹。 红色圆形弹丸 第三部分“广阔” 下面显示的是高级类图的图2该图描述了为此演示创建的所有类。 GameWorld和Sprite类是上一篇文章的游戏引擎的一部分。 其余的类是新的它们构成了本教程的演示。 InputPart3 InputPart3是运行游戏的驱动程序或主要JavaFX应用程序。 这将创建一个要初始化的GameWorld对象并开始游戏循环。 下面显示的是主要JavaFX应用程序Input Part3的源代码。 import carlfx.gameengine.GameWorld;
package carlfx.demos.navigateship;import javafx.application.Application;
import javafx.stage.Stage;/*** The main driver of the game.* author cdea*/
public class InputPart3 extends Application {GameWorld gameWorld new TheExpanse(59, JavaFX 2 GameTutorial Part 3 - Input);/*** param args the command line arguments*/public static void main(String[] args) {launch(args);}Overridepublic void start(Stage primaryStage) {// setup title, scene, stats, controls, and actors.gameWorld.initialize(primaryStage);// kick off the game loopgameWorld.beginGameLoop();// display windowprimaryStage.show();}} 广袤 TheExpanse类继承自GameWorld类。 这实际上与第2部分的“ AtomSmasher”相同在该部分中驱动程序应用程序将调用GameWorld实例的initialize方法来设置所有游戏元素例如input spaceship和那些讨厌的浮动球体 。 此类任务是确保小行星或球体从墙壁反弹并清除到达屏幕边缘的所有导弹。 负责任的主要是管理资产并创建新级别。 当没有移动物体并且玩家在屏幕上移动飞船时将为下一个级别生成新的球体。该类的关键是setupInput方法。 我创建的setupInput方法负责建立事件处理程序使其能够侦听键事件和鼠标事件。 package carlfx.demos.navigateship;import carlfx.gameengine.GameWorld;
import carlfx.gameengine.Sprite;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.CacheHint;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;import java.util.Random;/*** This is a simple game world simulating a bunch of spheres looking* like atomic particles colliding with each other. When the game loop begins* the user will notice random spheres (atomic particles) floating and* colliding. The user will navigate his/her ship by right clicking the mouse to* trust forward and left click to fire weapon to atoms.** author cdea*/
public class TheExpanse extends GameWorld {// mouse pt labelLabel mousePtLabel new Label();// mouse press pt labelLabel mousePressPtLabel new Label();TextField xCoordinate new TextField(234);TextField yCoordinate new TextField(200);Button moveShipButton new Button(Rotate ship);Ship myShip new Ship();public TheExpanse(int fps, String title) {super(fps, title);}/*** Initialize the game world by adding sprite objects.** param primaryStage The game window or primary stage.*/Overridepublic void initialize(final Stage primaryStage) {// Sets the window titleprimaryStage.setTitle(getWindowTitle());//primaryStage.setFullScreen(true);// Create the scenesetSceneNodes(new Group());setGameSurface(new Scene(getSceneNodes(), 800, 600));getGameSurface().setFill(Color.BLACK);primaryStage.setScene(getGameSurface());// Setup Game inputsetupInput(primaryStage);// Create many spheresgenerateManySpheres(2);// Display the number of spheres visible.// Create a button to add more spheres.// Create a button to freeze the game loop.//final Timeline gameLoop getGameLoop();getSpriteManager().addSprites(myShip);getSceneNodes().getChildren().add(myShip.node);// mouse pointVBox stats new VBox();HBox row1 new HBox();mousePtLabel.setTextFill(Color.WHITE);row1.getChildren().add(mousePtLabel);HBox row2 new HBox();mousePressPtLabel.setTextFill(Color.WHITE);row2.getChildren().add(mousePressPtLabel);stats.getChildren().add(row1);stats.getChildren().add(row2);// mouse pointHBox enterCoord1 new HBox();enterCoord1.getChildren().add(xCoordinate);enterCoord1.getChildren().add(yCoordinate);enterCoord1.getChildren().add(moveShipButton);stats.getChildren().add(enterCoord1);moveShipButton.setOnAction(new EventHandler() {Overridepublic void handle(ActionEvent actionEvent) {double x Double.parseDouble(xCoordinate.getText());double y Double.parseDouble(yCoordinate.getText());myShip.plotCourse(x, y, false);}});// // Debugging purposes// uncomment to test mouse press and rotation angles.//getSceneNodes().getChildren().add(stats);}/*** Sets up the mouse input.** param primaryStage The primary stage (app window).*/private void setupInput(Stage primaryStage) {System.out.println(Ships center is ( myShip.getCenterX() , myShip.getCenterY() ));EventHandler fireOrMove new EventHandler() {Overridepublic void handle(MouseEvent event) {mousePressPtLabel.setText(Mouse Press PT ( event.getX() , event.getY() ));if (event.getButton() MouseButton.PRIMARY) {// AimmyShip.plotCourse(event.getX(), event.getY(), false);// fireMissile m1 myShip.fire();getSpriteManager().addSprites(m1);getSceneNodes().getChildren().add(0, m1.node);} else if (event.getButton() MouseButton.SECONDARY) {// determine when all atoms are not on the game surface. Ship should be one sprite left.if (getSpriteManager().getAllSprites().size() generateManySpheres(30);}// stop ship from moving forwardmyShip.applyTheBrakes(event.getX(), event.getY());// move forward and rotate shipmyShip.plotCourse(event.getX(), event.getY(), true);}}};// Initialize inputprimaryStage.getScene().setOnMousePressed(fireOrMove);//addEventHandler(MouseEvent.MOUSE_PRESSED, me);// set up statsEventHandler changeWeapons new EventHandler() {Overridepublic void handle(KeyEvent event) {myShip.changeWeapon(event.getCode());}};primaryStage.getScene().setOnKeyPressed(changeWeapons);// set up statsEventHandler showMouseMove new EventHandler() {Overridepublic void handle(MouseEvent event) {mousePtLabel.setText(Mouse PT ( event.getX() , event.getY() ));}};primaryStage.getScene().setOnMouseMoved(showMouseMove);}/*** Make some more space spheres (Atomic particles)** param numSpheres The number of random sized, color, and velocity atoms to generate.*/private void generateManySpheres(int numSpheres) {Random rnd new Random();Scene gameSurface getGameSurface();for (int i 0; i numSpheres; i) { Color c Color.rgb(rnd.nextInt(255), rnd.nextInt(255), rnd.nextInt(255)); Atom b new Atom(rnd.nextInt(15) 5, c, true); Circle circle b.getAsCircle(); // random 0 to 2 (.0 to 1) * random (1 or -1) b.vX (rnd.nextInt(2) rnd.nextDouble()) * (rnd.nextBoolean() ? 1 : -1); b.vY (rnd.nextInt(2) rnd.nextDouble()) * (rnd.nextBoolean() ? 1 : -1); // random x between 0 to width of scene double newX rnd.nextInt((int) gameSurface.getWidth()); // check for the right of the width newX is greater than width // minus radius times 2(width of sprite) if (newX (gameSurface.getWidth() - (circle.getRadius() * 2))) {newX gameSurface.getWidth() - (circle.getRadius() * 2);}// check for the bottom of screen the height newY is greater than height// minus radius times 2(height of sprite)double newY rnd.nextInt((int) gameSurface.getHeight());if (newY (gameSurface.getHeight() - (circle.getRadius() * 2))) {newY gameSurface.getHeight() - (circle.getRadius() * 2);}circle.setTranslateX(newX);circle.setTranslateY(newY);circle.setVisible(true);circle.setId(b.toString());circle.setCache(true);circle.setCacheHint(CacheHint.SPEED);circle.setManaged(false);// add to actors in play (sprite objects)getSpriteManager().addSprites(b);// add spritesgetSceneNodes().getChildren().add(0, b.node);}}/*** Each sprite will update its velocity and bounce off wall borders.** param sprite - An atomic particle (a sphere).*/Overrideprotected void handleUpdate(Sprite sprite) {// advance objectsprite.update();if (sprite instanceof Missile) {removeMissiles((Missile) sprite);} else {bounceOffWalls(sprite);}}/*** Change the direction of the moving object when it encounters the walls.** param sprite The sprite to update based on the wall boundaries.* TODO The ship has got issues.*/private void bounceOffWalls(Sprite sprite) {// bounce off the walls when outside of boundariesNode displayNode;if (sprite instanceof Ship) {displayNode sprite.node;//((Ship)sprite).getCurrentShipImage();} else {displayNode sprite.node;}// Get the group nodes X and Y but use the ImageView to obtain the width.if (sprite.node.getTranslateX() (getGameSurface().getWidth() - displayNode.getBoundsInParent().getWidth()) ||displayNode.getTranslateX() 0) { // bounce the opposite direction sprite.vX sprite.vX * -1; } // Get the group nodes X and Y but use the ImageView to obtain the height. if (sprite.node.getTranslateY() getGameSurface().getHeight() - displayNode.getBoundsInParent().getHeight() ||sprite.node.getTranslateY() 0) { sprite.vY sprite.vY * -1; } } /** * Remove missiles when they reach the wall boundaries. * * param missile The missile to remove based on the wall boundaries. */ private void removeMissiles(Missile missile) { // bounce off the walls when outside of boundaries if (missile.node.getTranslateX() (getGameSurface().getWidth() -missile.node.getBoundsInParent().getWidth()) ||missile.node.getTranslateX() 0) { getSpriteManager().addSpritesToBeRemoved(missile); getSceneNodes().getChildren().remove(missile.node); } if (missile.node.getTranslateY() getGameSurface().getHeight() -missile.node.getBoundsInParent().getHeight() ||missile.node.getTranslateY() 0) {getSpriteManager().addSpritesToBeRemoved(missile);getSceneNodes().getChildren().remove(missile.node);}}/*** How to handle the collision of two sprite objects. Stops the particle* by zeroing out the velocity if a collision occurred.** param spriteA Sprite from the first list.* param spriteB Sprite from the second list.* return boolean returns a true if the two sprites have collided otherwise false.*/Overrideprotected boolean handleCollision(Sprite spriteA, Sprite spriteB) {if (spriteA ! spriteB) {if (spriteA.collide(spriteB)) {if (spriteA instanceof Atom spriteB instanceof Atom) {((Atom) spriteA).implode(this); // will remove from the Scene onFinish()((Atom) spriteB).implode(this);getSpriteManager().addSpritesToBeRemoved(spriteA, spriteB);return true;}}}return false;}} 船 Ship类代表我们很酷的太空飞船。 Ship类继承自Sprite类以帮助我们包含速度信息向量。 此类还将包含一个双向链接列表该列表包含32个ImageView RotatedShipImage 实例这些实例表示模拟船绕其中心质心旋转的每个方向。 在某些时候我想通过旋转单个SVGPath对象来更改此设置我知道有一些折衷方案。 在本教程中我通过将ImageView的对象从0到360度均匀旋转32方向来实现飞船。 下面的图3中显示的是使用32个ImageView实例和飞船图像的单个Image对象的所有32个方向以模拟围绕其中心枢轴点的旋转。 在给船旋转动画时我只需使用ImageView节点上的setVisibletrue方法将当前图像以外的所有图像设置为可见。 免责声明 在游戏中您不可避免地会遇到数学三角学。 如果您有兴趣并想进一步深入请查看TheExpanse类的initialize方法的源代码。 在方法的末尾取消注释该语句 getSceneNodes。getChildren。addstats; 。 这将显示控件使您可以用来调试和检查鼠标按下的坐标。 此外您还可以在控制台stdout中看到与角度向量等有关的输出。 船舶的成员变量 turnDirection –枚举DIRECTION顺时针逆时针且均不 u – Vec对象该对象包含相对于船舶坐标中心的矢量表示船舶开始旋转的起始方向 directionalShips – RotatedShipImage对象的列表每个对象具有对其他RotatedShipImage对象的上一个和下一个引用。 零度uIndex 0是太空飞船朝东的时间。 当旋转JavaFX节点时逆时针方向为正数以度为单位 uIndex –当前RotatedShipImage在directionShips列表中将显示的索引 vIndex –旋转动画结束时将显示的directionalShips列表中RotatedShipImage的索引 stopArea –一个JavaFX Circle其半径为船舶知道何时停止船舶移动 flipBook –包含所有RotatedShipImage对象的JavaFX组32。 该组将在场景上渲染。 就像动画中的翻书一样每个RotatedShipImage都将根据uIndex和vIndex确定要显示 keyCode – JavaFX KeyCode将帮助确定是否按键可以帮助您改变武器字符“ 2” 该船的会员职能 update –更新船只的速度和方向。 还将确定何时停止移动。 getCurrentShipImage –基于uIndex它返回ImageView该ImageView是正在显示的当前船方向图像 getCenterX –返回屏幕中心的X坐标 getCenterY –返回屏幕上船中心的X坐标 plotCoursedouble screenXdouble screenYboolean推力 –用户在屏幕上单击鼠标后此方法将计算旋转船的角度并更改速度以将坐标推向目标点。 使用Vec对象时屏幕坐标将转换为直角坐标以确定两个向量U和V之间的角度。 turnShip – plotCourse方法调用turnShip方法来执行船舶旋转的实际动画 applyTheBrakesdouble screenXdouble screenY –用户选择右键单击船只将导航至的位置applyTheBrakes方法只需设置stopArea Circle 对象即可让船只知道何时停止 fire –返回供游戏引擎放入场景中的导弹Sprite对象。 每个导弹都以增加的速度增加的速度包含与船相同的方向。 应该比飞船飞得更快。 changeWeaponKeyCode keyCode –用户玩家击键为2 武器将改变以产生更大的导弹射弹但速度稍慢。 其他任何按键操作都将是默认的武器它可以产生速度更快的小型导弹弹丸。 下面显示的是类图的图4显示了Ship类的成员。 船级图 下面显示的是Ship类的源代码。 package carlfx.demos.navigateship;import carlfx.gameengine.Sprite;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.animation.TimelineBuilder;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.CacheHint;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.image.Image;
import javafx.scene.input.KeyCode;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.util.Duration;
import java.util.ArrayList;
import java.util.List;/*** A space ship with 32 directions* When two atoms collide each will fade and become removed from the scene. The* method called implode() implements a fade transition effect.** author cdea*/
public class Ship extends Sprite {/*** 360 degree turn*/private final static int TWO_PI_DEGREES 360;/*** Number of ship frames and directions the ship is pointing nose*/private final static int NUM_DIRECTIONS 32;/*** The angle of one direction (adjacent directions) (11.25 degrees)*/private final static float UNIT_ANGLE_PER_FRAME ((float) TWO_PI_DEGREES / NUM_DIRECTIONS);/*** Amount of time it takes the ship to move 180 degrees in milliseconds.*/private final static int MILLIS_TURN_SHIP_180_DEGREES 300;/*** When the ship turns on each direction one amount of time for one frame or turn of the ship. (18.75 milliseconds)*/private final static float MILLIS_PER_FRAME (float) MILLIS_TURN_SHIP_180_DEGREES / (NUM_DIRECTIONS / 2);/*** All possible turn directions Clockwise, Counter Clockwise, or Neither when the user clicks mouse around ship*/private enum DIRECTION {CLOCKWISE, COUNTER_CLOCKWISE, NEITHER}/*** Velocity amount used vector when ship moves forward. scale vector of ship. See flipBook translateX and Y.*/private final static float THRUST_AMOUNT 3.3f;/***/private final static float MISSILE_THRUST_AMOUNT 6.3F;/*** Angle in degrees to rotate ship.*//*** Current turning direction. default is NEITHER. Clockwise and Counter Clockwise.*/private DIRECTION turnDirection DIRECTION.NEITHER;/*** The current starting position of the vector or coordinate where the nose of the ship is pointing towards.*/private Vec u; // current or start vector/*** All ImageViews of all the possible image frames for each direction the ship is pointing. ie: 32 directions.*/private final List directionalShips new ArrayList();/*** The Timeline instance to animate the ship rotating using images. This is an optical illusion similar to page* flipping as each frame is displayed the previous visible attribute is set to false. No rotation is happening.*/private Timeline rotateShipTimeline;/*** The current index into the list of ImageViews representing each direction of the ship. Zero is the ship* pointing to the right or zero degrees.*/private int uIndex 0;/*** The end index into the list of ImageViews representing each direction of the ship. Zero is the ship* pointing to the right or zero degrees.*/private int vIndex 0;/*** The spot where the user has right clicked letting the engine check the ships center is in this area.*/private final Circle stopArea new Circle();/*** A group contain all of the ship image view nodes.*/private final Group flipBook new Group();/*** A key code will be used for weapon selection.*/private KeyCode keyCode;public Ship() {// Load one image.Image shipImage new Image(getClass().getClassLoader().getResource(ship.png).toExternalForm(), true);stopArea.setRadius(40);RotatedShipImage prev null;// create all the number of directions based on a unit angle. 360 divided by NUM_DIRECTIONSfor (int i 0; i NUM_DIRECTIONS; i) {RotatedShipImage imageView new RotatedShipImage();imageView.setImage(shipImage);imageView.setRotate(-1 * i * UNIT_ANGLE_PER_FRAME);imageView.setCache(true);imageView.setCacheHint(CacheHint.SPEED);imageView.setManaged(false);imageView.prev prev;imageView.setVisible(false);directionalShips.add(imageView);if (prev ! null) {prev.next imageView;}prev imageView;flipBook.getChildren().add(imageView);}RotatedShipImage firstShip directionalShips.get(0);firstShip.prev prev;prev.next firstShip;// set javafx node to an imagefirstShip.setVisible(true);node flipBook;flipBook.setTranslateX(200);flipBook.setTranslateY(300);}/*** Change the velocity of the atom particle.*/Overridepublic void update() {flipBook.setTranslateX(flipBook.getTranslateX() vX);flipBook.setTranslateY(flipBook.getTranslateY() vY);if (stopArea.contains(getCenterX(), getCenterY())) {vX 0;vY 0;}}private RotatedShipImage getCurrentShipImage() {return directionalShips.get(uIndex);}/*** The center X coordinate of the current visible image. See codegetCurrentShipImage()/code method.** return The scene or screen X coordinate.*/public double getCenterX() {RotatedShipImage shipImage getCurrentShipImage();return node.getTranslateX() (shipImage.getBoundsInLocal().getWidth() / 2);}/*** The center Y coordinate of the current visible image. See codegetCurrentShipImage()/code method.** return The scene or screen Y coordinate.*/public double getCenterY() {RotatedShipImage shipImage getCurrentShipImage();return node.getTranslateY() (shipImage.getBoundsInLocal().getHeight() / 2);}/*** Determines the angle between its starting position and ending position (Similar to a clocks second hand).* When the user is shooting the ship nose will point in the direction of the mouse press using the primary button.* When the user is thrusting to a location on the screen the right click mouse will pass true to the thrust* parameter.** param screenX The mouse press screen x coordinate.* param screenY The mouse press screen ycoordinate.* param thrust Thrust ship forward or not. True move forward otherwise false.*/public void plotCourse(double screenX, double screenY, boolean thrust) {// get center of shipdouble sx getCenterX();double sy getCenterY();// get users new turn position based on mouse clickVec v new Vec(screenX, screenY, sx, sy);if (u null) {u new Vec(1, 0);}double atan2RadiansU Math.atan2(u.y, u.x);double atan2DegreesU Math.toDegrees(atan2RadiansU);double atan2RadiansV Math.atan2(v.y, v.x);double atan2DegreesV Math.toDegrees(atan2RadiansV);double angleBetweenUAndV atan2DegreesV - atan2DegreesU;// if abs value is greater than 180 move counter clockwise//(or opposite of what is determined)double absAngleBetweenUAndV Math.abs(angleBetweenUAndV);boolean goOtherWay false;if (absAngleBetweenUAndV 180) {if (angleBetweenUAndV 0) { turnDirection DIRECTION.COUNTER_CLOCKWISE; goOtherWay true; } else if (angleBetweenUAndV 0) {turnDirection DIRECTION.CLOCKWISE;goOtherWay true;} else {turnDirection Ship.DIRECTION.NEITHER;}} else {if (angleBetweenUAndV 0) { turnDirection Ship.DIRECTION.CLOCKWISE; } else if (angleBetweenUAndV 0) {turnDirection Ship.DIRECTION.COUNTER_CLOCKWISE;} else {turnDirection Ship.DIRECTION.NEITHER;}}double degreesToMove absAngleBetweenUAndV;if (goOtherWay) {degreesToMove TWO_PI_DEGREES - absAngleBetweenUAndV;}//int q v.quadrant();uIndex Math.round((float) (atan2DegreesU / UNIT_ANGLE_PER_FRAME));if (uIndex 0) {uIndex NUM_DIRECTIONS uIndex;}vIndex Math.round((float) (atan2DegreesV / UNIT_ANGLE_PER_FRAME));if (vIndex 0) { vIndex NUM_DIRECTIONS vIndex; } String debugMsg turnDirection U [m( u.mx , u.my ) c( u.x , u.y )] V [m( v.mx , v.my ) c( v.x , v.y )] start angle: atan2DegreesU end angle: atan2DegreesV Angle between: degreesToMove Start index: uIndex End index: vIndex;System.out.println(debugMsg);if (thrust) {vX Math.cos(atan2RadiansV) * THRUST_AMOUNT;vY -Math.sin(atan2RadiansV) * THRUST_AMOUNT;}turnShip();u v;}private void turnShip() {final Duration oneFrameAmt Duration.millis(MILLIS_PER_FRAME);RotatedShipImage startImage directionalShips.get(uIndex);RotatedShipImage endImage directionalShips.get(vIndex);List frames new ArrayList();RotatedShipImage currImage startImage;int i 1;while (true) {final Node displayNode currImage;KeyFrame oneFrame new KeyFrame(oneFrameAmt.multiply(i),new EventHandler() {Overridepublic void handle(javafx.event.ActionEvent event) {// make all ship images invisiblefor (RotatedShipImage shipImg : directionalShips) {shipImg.setVisible(false);}// make current ship image visibledisplayNode.setVisible(true);// update the current index//uIndex directionalShips.indexOf(displayNode);}}); // oneFrameframes.add(oneFrame);if (currImage endImage) {break;}if (turnDirection DIRECTION.CLOCKWISE) {currImage currImage.prev;}if (turnDirection DIRECTION.COUNTER_CLOCKWISE) {currImage currImage.next;}i;}if (rotateShipTimeline ! null) {rotateShipTimeline.stop();rotateShipTimeline.getKeyFrames().clear();rotateShipTimeline.getKeyFrames().addAll(frames);} else {// sets the game worlds game loop (Timeline)rotateShipTimeline TimelineBuilder.create().keyFrames(frames).build();}rotateShipTimeline.playFromStart();}/*** Stops the ship from thrusting forward.** param screenX the screens X coordinate to stop the ship.* param screenY the screens Y coordinate to stop the ship.*/public void applyTheBrakes(double screenX, double screenY) {stopArea.setCenterX(screenX);stopArea.setCenterY(screenY);}public Missile fire() {Missile m1;float slowDownAmt 0;if (KeyCode.DIGIT2 keyCode) {m1 new Missile(10, Color.BLUE);slowDownAmt 2.3f;} else {m1 new Missile(Color.RED);}// velocity vector of the missilem1.vX Math.cos(Math.toRadians(uIndex * UNIT_ANGLE_PER_FRAME)) * (MISSILE_THRUST_AMOUNT - slowDownAmt);m1.vY -Math.sin(Math.toRadians(uIndex * UNIT_ANGLE_PER_FRAME)) * (MISSILE_THRUST_AMOUNT - slowDownAmt);// make the missile launch in the direction of the current direction of the ship nose. based on the// current frame (uIndex) into the list of image view nodes.RotatedShipImage shipImage directionalShips.get(uIndex);// start to appear in the center of the ship to come out the direction of the nose of the ship.double offsetX (shipImage.getBoundsInLocal().getWidth() - m1.node.getBoundsInLocal().getWidth()) / 2;double offsetY (shipImage.getBoundsInLocal().getHeight() - m1.node.getBoundsInLocal().getHeight()) / 2;// initial launch of the missilem1.node.setTranslateX(node.getTranslateX() offsetX m1.vX);m1.node.setTranslateY(node.getTranslateY() offsetY m1.vY);return m1;}public void changeWeapon(KeyCode keyCode) {this.keyCode keyCode;}} Vec Vec类是一个简单的帮助程序容器类可帮助保持鼠标单击的屏幕坐标并根据子画面图像或形状的中心将其转换为笛卡尔坐标。 此类用于帮助确定两个向量[Math.atan2yx]之间的角度。 通过确定角度船可以执行子画面图像的旋转动画。 下面显示的是Vec类的源代码。 package carlfx.demos.navigateship;/*** This class represents a container class to hold a Vector in space and direction* the ship will move. Assuming the center of the ship is the origin the angles can* be determined by a unit circle via Cartesian coordinates.* When the user clicks on the screen the mouse coordinates or screen coordinates* will be stored into the mx and my instance variables.* The x and y data members are converted to cartesian coordinates before storing.** I purposefully left out getters and setters. In gaming just keep things minimalistic.* author cdea*/
public class Vec {public double mx;public double my;public double x;public double y;/*** This is a default constructor which will take a Cartesian coordinate.* param x X coordinate of a point on a Cartesian system.* param y Y coordinate of a point on a Cartesian system.*/public Vec(float x, float y) {this.x x;this.y y;}/*** Constructor will convert mouse click points into Cartesian coordinates based on the sprites center point as* the origin.* param mx Mouse press screen X coordinate.* param my Mouse press screen Y coordinate.* param centerX Screen X coordinate of the center of the ship sprite.* param centerY Screen Y coordinate of the center of the ship sprite.*/public Vec(double mx, double my, double centerX, double centerY) {this.x convertX(mx, centerX);this.y convertY(my, centerY);this.mx mx;this.my my;}/*** Returns a Cartesian coordinate systems quadrant from 1 to 4.
** first quadrant - 1 upper right* second quadrant - 2 upper left* third quadrant - 3 lower left* fourth quadrant - 4 lower right** return int quadrant number 1 through 4*/public int quadrant() {int q 0;if (x 0 y 0) {q 1;} else if (x 0 y 0) {q 2;} else if (x 0 y 0) { q 3; } else if (x 0 y 0) {q 4;}return q;}Overridepublic String toString(){return ( x , y ) quadrant quadrant();}/*** Converts points X screen coordinate into a Cartesian system.* param mouseX Converts the mouse X coordinate into Cartesian system based on the ship center X (originX).* param originX The ship center points X coordinate.* return double value of a Cartesian system X coordinate based on the origin X.*/static double convertX(double mouseX, double originX) {return mouseX - originX;}/*** Converts points Y screen coordinate into a Cartesian system.* param mouseY Converts the mouse Y coordinate into Cartesian system based on the ship center Y (originY).* param originY The ship center points Y coordinate.* return double value of a Cartesian system Y coordinate based on the origin Y.*/static double convertY(double mouseY, double originY) {return originY - mouseY;}} RotatedShipImage RotatedShipImage类继承自JavaFX的ImageView类但还包含对上一个和下一个RotatedShipImage实例的引用 这些实例构成了一个双向链接列表。 图3描绘了在每个RotatedShipImage中呈现的“ ship.png”的32个图像它们全部放置在JavaFX Group节点中。 当船似乎在旋转时一次只显示一幅图像。 下面显示的是RotatedShipImage类的源代码。 package carlfx.demos.navigateship;import javafx.scene.image.ImageView;/*** Represents a double link list to assist in the rotation of the ship.* This helps to move clockwise and counter clockwise.*/
public class RotatedShipImage extends ImageView {public RotatedShipImage next;public RotatedShipImage prev;
} 导弹 Missile类继承自Atom类。 导弹是标记物用于区分小球和导弹。 制造导弹后它们将以更大的速度包含与船相同的方向船鼻指向的方向。 下面显示的是Missile类的源代码。 package carlfx.demos.navigateship;import javafx.scene.paint.Color;/*** A missile projectile without the radial gradient.*/
public class Missile extends Atom {public Missile(Color fill) {super(5, fill, false);}public Missile(int radius, Color fill) {super(radius, fill, true);}
} 结论 输入对任何游戏都至关重要因此通常很难正确输入。 较旧的游戏引擎将在游戏循环中进行轮询。 使用JavaFX 2.x的事件处理时可以实现要添加到场景图或单个Node对象中的事件类型。 希望在将来我们将看到更多用于游戏的巧妙输入设备请参阅Oracle的Java技术推广员Simon Ritter 。 睁大眼睛看一下第4部分它涉及碰撞检测。 因此请继续关注并随时发表评论。 有用的链接 7-11 http//www.7-eleven.com 玩小行星 http://www.play.vg/games/4-Asteroids.html 小行星 http://en.wikipedia.org/wiki/Asteroids_(video_game 斯科特·萨夫兰Scott Safran http://en.wikipedia.org/wiki/Scott_Safran 后院拱廊 http://www.themysteryworld.com/2011/02/guy-builds-video-arcade-in-his-back.html 缩小《星战》 http://techland.time.com/2012/04/26/man-builds-16-scale-star-wars-arcade-game/ 三角学 http//en.wikipedia.org/wiki/ 三角学 JavaFX节点API http://docs.oracle.com/javafx/2/api/javafx/scene/Node.html JavaFX Scene API http://docs.oracle.com/javafx/2/api/javafx/scene/Scene.html JavaFX SVGPath API http: //docs.oracle.com/javafx/2/api/javafx/scene/shape/SVGPath.html 多点触控和手势支持 http://www.oracle.com/technetwork/java/javafx/overview/roadmap-1446331.html Pro JavaFX 2 Apress发布– pg。 62第2章第2节“处理输入事件”。 http://www.apress.com/9781430268727 Java 7 Recipe Apress发行-第pg。 602第16章食谱16-3“沿路径动画制作形状”。 http://www.apress.com/9781430240563 电子游戏厅柜 http//en.wikipedia.org/wiki/Video_game_arcade_cabinet 栅格图形 http://en.wikipedia.org/wiki/Raster_graphics GitHub上的第3部分源代码 https://github.com/carldea/JFXGen/tree/master/demos/navigateship JavaFX Canvas节点 http://mail.openjdk.java.net/pipermail/openjfx-dev/2012-April/001210.html JavaFX-为JavaFX应用程序优化性能 http//www.parleys.com/#st5id2738sl0 甲骨文的Java技术推广员Simon Ritter https://blogs.oracle.com/javaone/entry/interface_with_the_interface_javafx 视频游戏高中第1集 http//www.rocketjump.com/video vghs-episode-1 视频游戏高中第2集 http//www.rocketjump.com/video vghs-episode-2-5 参考来自我们的JCG合作伙伴 Carl Dea的JavaFX 2 GameTutorial第3部分 位于Carls FX Blog博客上。 翻译自: https://www.javacodegeeks.com/2012/05/javafx-2-gametutorial-part-3.html