/* * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. */ package guimark2; import java.util.ArrayList; import java.util.List; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.paint.Color; import javafx.scene.shape.Line; import javafx.scene.shape.Rectangle; import javafx.application.Application; /** * User: Artem Ananiev, Brent Christian * Date: Sep 23, 2010 * Time: 1:50:35 PM * * BitmapTest implemented using the scenegraph. */ public class BitmapTest extends BitmapBase { protected final int LASER_COUNT = 8; // Configuration options: private static boolean alwaysmove = false; private static final int numtomove = Integer.MAX_VALUE; private static boolean usefrontback = true; // Scenegraph GUI elementss private BitmapMonster[] monsters; private final List explosions = new ArrayList(LASER_COUNT); private Group group; private Group monsterGroup; private Group explosionsGroup; private ImageView towerView; private ImageView towerTopView; private Rectangle groupClip; @Override protected void initMonsters() { monsters = new BitmapMonster[monster_count]; for (int i = 0; i < monster_count; i++) { float dir = (float) (RAND.nextFloat() * 2 * Math.PI); List frames; if ((dir > Math.PI / 4) && (dir <= Math.PI * 3 / 4)) { frames = southImages; } else if ((dir > Math.PI * 3 / 4) && (dir <= Math.PI * 5 / 4)) { frames = westImages; } else if ((dir > Math.PI * 5 / 4) && (dir <= Math.PI * 7 / 4)) { frames = northImages; } else { frames = eastImages; } monsters[i] = new BitmapMonster(W, H, frames, dir); } } @Override protected void initExplosions() { List expImages = new ArrayList(8); for (int i = 1; i <= 8; i++) { expImages.add(images.get("Bomb" + i)); } for (int i = 0; i < LASER_COUNT; i++) { explosions.add(new ExplosionData(expImages, i)); } } @Override protected Scene initScene() { Scene newScene = new Scene(new Group(), W, H + FPS_HEIGHT); fpsLabel = new Label("FPS"); ((Group) newScene.getRoot()).getChildren().add(fpsLabel); group = new Group(); group.setTranslateY(FPS_HEIGHT); groupClip = new Rectangle(W, H); group.setClip(groupClip); ((Group) newScene.getRoot()).getChildren().add(group); for (float x = 0; x < W; x += bgImage.getWidth()) { for (float y = 0; y < H; y += bgImage.getHeight()) { ImageView bgView = new ImageView(); bgView.setImage(bgImage); bgView.setTranslateX(x); bgView.setTranslateY(y); group.getChildren().add(bgView); } } monsterGroup = new Group(); for (BitmapMonster monster : monsters) { monsterGroup.getChildren().add(monster.getView()); } towerView = new ImageView(); towerView.setImage(images.get("Tower")); // Tower is 160x288 // Other versions draw tower at 550, 100 for a 1200x600 pixel window // Offset from center of that window would be (-50, -200) towerView.setTranslateX(W / 2 - 50); towerView.setTranslateY(H / 2 - 200); monsterGroup.getChildren().add(towerView); group.getChildren().add(monsterGroup); explosionsGroup = new Group(); for (ExplosionData exp : explosions) { explosionsGroup.getChildren().add(exp.getView()); explosionsGroup.getChildren().add(exp.getLine()); } towerTopView = new ImageView(); towerTopView.setImage(images.get("TowerTop")); // Tower top is 88x79 // Other versions draw tower top at 570,124 // so tt.translation = t.translation + (20,24) towerTopView.setTranslateX(towerView.getTranslateX() + 20); towerTopView.setTranslateY(towerView.getTranslateY() + 24); explosionsGroup.getChildren().add(towerTopView); group.getChildren().add(explosionsGroup); return newScene; } @Override protected void testIteration() { int n = numtomove; for (BitmapMonster monster : monsters) { ImageView view = monster.getView(); boolean wastop = monster.top(); boolean nowtop = monster.step(W, H); if (n > 0 && (alwaysmove || wastop != nowtop)) { if (nowtop) { if (usefrontback) { view.toBack(); } else { monsterGroup.getChildren().remove(view); monsterGroup.getChildren().add(0, view); } } else { if (usefrontback) { view.toFront(); } else { monsterGroup.getChildren().remove(view); monsterGroup.getChildren().add(view); } } --n; } } for (ExplosionData explosion : explosions) { // Other versions shoot lasers from 612,180 for a 1200x600 window // Explosions erupt in a 200 radius circle centered on 520,270 // with the lasers biased by 83,70 from that location // these are relative to the tower top drawn at 570,124 double ttx = towerTopView.getTranslateX(); double tty = towerTopView.getTranslateY(); explosion.step(ttx + 42, tty + 56, ttx - 50, tty + 146, Math.min(W / 3, H / 3)); } } public static void parseOptions(String[] args) { baseParseOptions(args); for (int index = 0; index < args.length; index++) { String arg = args[index]; if("-alwaysmove".equals(arg)) { alwaysmove = true; } else if("-usefrontback".equals(arg)) { usefrontback = true; } else if("-useaddremove".equals(arg)) { usefrontback = false; } } System.out.println("alwaysmove: " + alwaysmove); System.out.println("usefrontback: " + usefrontback); } public static void main(String[] args) { parseOptions(args); Application.launch(BitmapTest.class, args); } private class ExplosionData { private int curFrame; private List frames; private ImageView view; private Line line; public ExplosionData(List fs, int index) { curFrame = index % fs.size(); frames = fs; view = new ImageView(); view.setVisible(false); line = new Line(); line.setStrokeWidth(3); line.setStroke(Color.YELLOW); line.setVisible(false); } public ImageView getView() { return view; } public Line getLine() { return line; } public void step(double tx, double ty, double cx, double cy, double cr) { Image curImage; if (++curFrame == frames.size()) { curFrame = 0; curImage = frames.get(0); double a = RAND.nextFloat() * 2 * Math.PI; double x = cx + cr * Math.cos(a); double y = cy + cr * Math.sin(a); view.setVisible(true); view.setTranslateX(x); view.setTranslateY(y); line.setVisible(true); line.setStartX(tx); line.setStartY(ty); line.setEndX(x + 83.0); line.setEndY(y + 70.0); } else { curImage = frames.get(curFrame); line.setVisible(false); } view.setImage(curImage); } } /** * User: Artem * Date: Sep 23, 2010 * Time: 3:38:38 PM */ private class BitmapMonster { private float x; private float y; private float dx; private float dy; private boolean top; private float scale; private int curFrame; private List frames; private ImageView view; public BitmapMonster(int w, int h, List fs, float dir) { x = RAND.nextFloat() * w; y = RAND.nextFloat() * h; float speed = 3 + (RAND.nextFloat() * 2); dx = (float) Math.cos(dir) * speed; dy = (float) Math.sin(dir) * speed; scale = 0.5f + RAND.nextFloat() * 0.7f; curFrame = Math.abs(RAND.nextInt()) % fs.size(); frames = fs; view = new ImageView(); updateTop(h); } private void updateTop(double h) { // Other versions reorder the monsters when they cross y=330 // for a 600 pixel tall window top = (y < h / 2 + 30); } public boolean top() { return top; } public boolean step(double w, double h) { x += dx; y += dy; validateXY(w, h); curFrame = (curFrame + 1) % frames.size(); Image curImage = frames.get(curFrame); double imageW = curImage.getWidth(); double imageH = curImage.getHeight(); view.setImage(curImage); view.setTranslateX(x); view.setTranslateY(y); view.setRotationAxis(javafx.scene.transform.Rotate.Y_AXIS); view.setRotate(42.); // OPT: Can pre-compute these once in the ctor... view.setFitWidth(imageW * scale); view.setFitHeight(imageH * scale); updateTop(h); return top; } private void validateXY(double w, double h) { if (x < -40) { x += w + 40; } else if (x > w) { x -= w + 40; } if (y < -40) { y += h + 40; } else if (y > h) { y -= h + 40; } if (x > w - 100 && y < 50) { x -= w - 100; y += h - 50; } } public ImageView getView() { return view; } } }