/*** * * Copyright (C) 2008 Alessandro La Rosa * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: alessandro.larosa@gmail.com * * Author: Alessandro La Rosa */ package com.jappit.japdarts.display; import java.util.Random; import javax.microedition.lcdui.Canvas; import javax.microedition.lcdui.Font; import javax.microedition.lcdui.Graphics; import com.jappit.japdarts.app.JapDarts; import com.jappit.japdarts.utils.ScoreManager; public class DartScreen extends Canvas implements Runnable { boolean changed = true; final static int MILLIS_PER_TICK = 50; Font font = null; int doneDarts = 0; int totalDarts = 5; int[][] darts = null; int circles = 8; int[] circlePoints = new int[]{10, 8, 6, 5, 4, 3, 2, 1}; public int points = 0; boolean scoreChanged = true; int[] circleColors = new int[]{0xffffff, 0x000000}; int maxPointerShift = 0; int pointerMove = 0; int dartColor = 0xff0000; int bgColor = 0x009900; int circleWidth = 0; int padding = 10; int centerX = 0; int centerY = 0; int pointerX = 0; int pointerY = 0; int gameWidth = 0; int gameHeight = 0; int boardWidth = 0; int boardHeight = 0; int footerHeight = 0; int slidePad = 4; int slideWidth = 16; int slideX = 0; int slideY = 0; int slideMove = 20; int slideDir = 1; int STATE_MOVING = 0; int STATE_XSLIDE = 1; int STATE_YSLIDE = 2; int STATE_LAUNCHING = 3; int STATE_WAITING = 4; int targetX = 0; int targetY = 0; int dartX = 0; int dartY = 0; int dartMove = 0; int dartStartX = 0; int dartStartY = 0; int dartSteps = 10; int dartCurrentStep = 0; int[] dartYDeltas = new int[]{2, 4, 6, 8, 10, 8, 6, 4, 2, 0}; int state = STATE_MOVING; Random rand = null; int currentKey = Integer.MIN_VALUE; public DartScreen() { font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL); darts = new int[][]{ new int[]{0, 0},new int[]{0, 0},new int[]{0, 0},new int[]{0, 0},new int[]{0, 0} }; rand = new Random(); footerHeight = font.getHeight() + 2; initializeSizes(); new Thread(this).start(); } public void newGame() { initializePositions(); doneDarts = 0; points = 0; scoreChanged = true; state = STATE_MOVING; } void initializeSizes() { gameWidth = getWidth(); gameHeight = getHeight() - footerHeight; boardWidth = gameWidth - slideWidth; boardHeight = gameHeight - slideWidth; circleWidth = (Math.min(boardWidth, boardHeight) - 2 * padding) / circles; centerX = boardWidth / 2; centerY = boardHeight / 2; pointerX = centerX; pointerY = centerY; maxPointerShift = circleWidth / 3; pointerMove = circleWidth / 4; dartStartX = 0; dartStartY = boardHeight; initializePositions(); } protected void sizeChanged(int w, int h) { initializeSizes(); } void initializePositions() { dartX = dartStartX; dartY = dartStartY; pointerX = nextInt(boardWidth); pointerY = nextInt(boardHeight); slideX = 0; slideY = 0; currentKey = Integer.MIN_VALUE; } protected void paint(Graphics g) { if(state != STATE_XSLIDE && state != STATE_YSLIDE) { g.setColor(bgColor); g.fillRect(0, 0, gameWidth, gameHeight); for(int i = 0; i < circles; i++) { g.setColor(circleColors[i % 2]); int radius = (circles - i) * circleWidth/ 2; g.fillArc(centerX - radius, centerY - radius, radius * 2, radius * 2, 0, 360); } paintDoneDarts(g); } paintSlides(g); if(state == STATE_LAUNCHING) { paintDart(g); } else if(state != STATE_WAITING) { paintPointer(g); } if(scoreChanged) { g.translate(0, gameHeight); paintFooter(g); g.translate(0, - gameHeight); } } void paintSlides(Graphics g) { g.setColor(0x000000); int pointRadius = slideWidth / 2 - 1; g.fillRoundRect(gameWidth - slideWidth - slidePad / 2, slidePad, slideWidth, gameHeight - 2 * slidePad - slideWidth, slideWidth / 2, slideWidth / 2); g.fillRoundRect(slidePad, gameHeight - slideWidth - slidePad / 2, gameWidth - 2 * slidePad - slideWidth, slideWidth, slideWidth / 2, slideWidth / 2); g.setColor(0xff0000); int y = pointRadius + slidePad + (100 + slideY) * (gameHeight - 2 * slidePad - slideWidth - 2 * pointRadius) / (2 * 100); int x = pointRadius + slidePad + (100 + slideX) * (gameWidth - 2 * slidePad - slideWidth - 2 * pointRadius) / (2 * 100); g.fillArc(gameWidth - slideWidth / 2 - pointRadius - slidePad / 2, y - pointRadius, pointRadius * 2, pointRadius * 2, 0, 360); g.fillArc(x - pointRadius, gameHeight - slideWidth / 2 - pointRadius - slidePad / 2, pointRadius * 2, pointRadius * 2, 0, 360); } void paintFooter(Graphics g) { scoreChanged = false; g.setColor(bgColor); g.fillRect(0, 0, gameWidth, footerHeight); g.setColor(0xffffff); g.setFont(font); g.drawString("pts " + points, 1, footerHeight - 1, Graphics.LEFT | Graphics.BOTTOM); g.drawString((totalDarts - doneDarts) + " darts", gameWidth - 1, footerHeight - 1, Graphics.RIGHT | Graphics.BOTTOM); } void paintPointer(Graphics g) { g.setColor(dartColor); int dartSize = 4; g.drawLine(pointerX - dartSize, pointerY, pointerX + dartSize, pointerY); g.drawLine(pointerX, pointerY - dartSize, pointerX, pointerY + dartSize); //g.fillArc(pointerX - dartRadius, pointerY - dartRadius, dartRadius * 2, dartRadius * 2, 0, 360); } void paintDart(Graphics g) { g.setColor(dartColor); int diff = targetX - dartX; int size = diff > (targetX - dartX) / 2 ? 10 : 20; g.drawLine(dartX - size, dartY - size, dartX + size, dartY + size); g.drawLine(dartX - size, dartY + size, dartX + size, dartY - size); g.drawArc(dartX - size / 2, dartY - size / 2, size, size, 0, 360); } void paintDoneDarts(Graphics g) { int dartSize = 5; g.setColor(dartColor); for(int i = 0; i < doneDarts; i++) { g.drawLine(darts[i][0] - dartSize, darts[i][1] - dartSize, darts[i][0] + dartSize, darts[i][1] + dartSize); g.drawLine(darts[i][0] + dartSize, darts[i][1] - dartSize, darts[i][0] - dartSize, darts[i][1] + dartSize); } } void movePointer() { pointerX += nextInt(2 * maxPointerShift) - maxPointerShift; pointerY += nextInt(2 * maxPointerShift) - maxPointerShift; pointerX = Math.max(0, Math.min(boardWidth, pointerX)); pointerY = Math.max(0, Math.min(boardHeight, pointerY)); } protected void keyPressed(int key) { currentKey = getGameAction(key); if(currentKey == Canvas.FIRE) { if(state == STATE_MOVING) { state = STATE_XSLIDE; } else if(state == STATE_XSLIDE) { state = STATE_YSLIDE; } else if(state == STATE_YSLIDE) { setTarget(); state = STATE_LAUNCHING; } } else if(isRightSoftKey(key)) { JapDarts.instance.setScreen(new MainMenu()); } } protected static boolean isRightSoftKey(int key) { return key == -22 || key == -7 || key == Canvas.KEY_POUND || key == 57346; } void setTarget() { targetX = pointerX + boardWidth * slideX / (2 * 100); targetY = pointerY + boardHeight * slideY / (2 * 100); dartMove = Math.max(1, targetX / 10); dartCurrentStep = 0; darts[doneDarts][0] = targetX; darts[doneDarts][1] = targetY; } protected void keyReleased(int key) { currentKey = Integer.MIN_VALUE; } void evalKey() { switch(currentKey) { case Canvas.RIGHT: pointerX += pointerMove; break; case Canvas.LEFT: pointerX -= pointerMove; break; case Canvas.UP: pointerY -= pointerMove; break; case Canvas.DOWN: pointerY += pointerMove; break; } } void moveXSlide() { slideX += slideDir * slideMove; if(slideX >= 100 || slideX <= -100) { slideDir *= -1; } } void moveYSlide() { slideY += slideDir * slideMove; if(slideY >= 100 || slideY <= -100) { slideDir *= -1; } } void moveDart() { dartX += dartMove; dartCurrentStep++; if(dartCurrentStep == dartSteps) { dartX = targetX; dartY = targetY; } else { dartY = dartStartY + dartX * (targetY - dartStartY) / targetX; } } void addPoints() { int diff = Math.max(Math.abs(targetX - centerX), Math.abs(targetY - centerY)); int scoreIndex = 2 * diff / circleWidth; if(scoreIndex < circles) { points += circlePoints[scoreIndex]; } scoreChanged = true; } void checkDartEnd() { if(dartX == targetX && dartY == targetY) { addPoints(); state = STATE_MOVING; initializePositions(); doneDarts++; if(doneDarts >= totalDarts) { state = STATE_WAITING; if(ScoreManager.getInstance().isRecord(points)) { JapDarts.instance.setScreen(new NewRecordScreen(points)); } else { JapDarts.instance.setScreen(new BestScoresScreen()); } } } } int nextInt(int max) { int n = rand.nextInt(); return n < 0 ? (- n) % max : n % max; } public void beforePaint() { if(state == STATE_MOVING) { evalKey(); movePointer(); } else if(state == STATE_XSLIDE) { moveXSlide(); } else if(state == STATE_YSLIDE) { moveYSlide(); } else if(state == STATE_LAUNCHING) { moveDart(); } if(state != STATE_WAITING) { notifyChange(); } } public void afterPaint() { if(state == STATE_LAUNCHING) { checkDartEnd(); } } protected void onScreenShow() { newGame(); } void notifyChange() { changed = true; } public void run() { while(true) { try { long startTime = System.currentTimeMillis(); beforePaint(); if(changed) { repaint(); } afterPaint(); long timeTaken = System.currentTimeMillis() - startTime; if( timeTaken < MILLIS_PER_TICK ) { synchronized ( this ) { wait(MILLIS_PER_TICK - timeTaken); } } } catch(Exception e) { e.printStackTrace(); } } } }