» »

[Java] Zasnova shoot em up igre

[Java] Zasnova shoot em up igre

PecenkA ::

Pozdravljeni

Danes sem na hitro sprogramiral čisto osnovo za shoot em up igro, za katero imam idejo v glavi že dolgo časa. Če se komu da, bi lepo prosil, da poda mnenja na sledečo kodo. Razvidno je, da me čaka še ogromno dela, vendar bi rad vedel, če in kje sem ga že v startu polomil.

Main funkcija (VShooter.java)
package vshooter;

import javax.swing.JFrame;

public class VShooter {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        //Load settings from game.propertis
        if (Settings.Load() == true) {
            //init frame, game, keylistener, input
            JFrame frame = new JFrame("VShooter");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            Game gm = new Game();
            frame.add(gm);
            Input in = new Input();
            frame.addKeyListener(in);
            frame.setSize(800, 600);        //sets frame size when not maximized
            frame.setExtendedState(frame.getExtendedState()|JFrame.MAXIMIZED_BOTH);         //maximize frame
            frame.setVisible(true);
            gm.Start();     //start game
        }
    }
}


Igra (Game.java)
package vshooter;

import java.awt.Graphics;
import javax.swing.JPanel;

public class Game extends JPanel {
    
    static float factorX;
    static float factorY;
    static double dT;       //frame time deltaTime
    private float resX;     //level design resolution horizontal
    private float resY;     //level design resolution vertical
    
    private GameObject go;          //test
    
    //Constructor
    Game() {
        //set object design resolution
        resX = 800f;
        resY = 600f;
        //Initialize object resizing factors
        factorX = (float)this.getWidth() / resX;
        factorY = (float)this.getHeight() / resY;
    }
    
    //Start Game
    void Start() {
        double pT;      //previous time
        double cT;      //current time
        pT = (double)System.nanoTime() / 1000000000;    //conversion to seconds
        cT = (double)System.nanoTime() / 1000000000;    //conversion to seconds
        
        go = new GameObject();      //test
        
        //Game loop
        while (1 == 1) {
            //Factor for object resizing to frame size
            factorX = (float)this.getWidth() / resX;
            factorY = (float)this.getHeight() / resY;
            //Set current time and calculate frame duration
            cT = (double)System.nanoTime() / 1000000000;        //conversion to seconds
            dT = cT - pT;
            //Update
            Update();
            //Draw
            this.repaint();
            //Set previous time
            pT = cT;
        }
    }
    
    void Update() {
        go.Update();    //test
    }
    
    void Draw(Graphics g) {
        go.Draw(g);     //test
        //FPS counter
        g.drawString("FPS: " + Double.toString(1 / dT), (int)(10 * factorX), (int)(20 * factorY));
        //test - input status
        if (Input.moveLeft == true) {
            g.drawString("Move left", (int)(10 * factorX), (int)(35 * factorY));
        }
        if (Input.moveRight == true) {
            g.drawString("Move right", (int)(10 * factorX), (int)(50 * factorY));
        }
        if (Input.moveUp == true) {
            g.drawString("Move up", (int)(10 * factorX), (int)(65 * factorY));
        }
        if (Input.moveDown == true) {
            g.drawString("Move down", (int)(10 * factorX), (int)(80 * factorY));
        }
        if (Input.fireP == true) {
            g.drawString("Fire primary weapon", (int)(10 * factorX), (int)(95 * factorY));
        }
        if (Input.fireS == true) {
            g.drawString("Fire secondary weapon", (int)(10 * factorX), (int)(110 * factorY));
        }
    }
    
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Draw(g);
    }
    
}


En testni objekt (GameObject.java)
package vshooter;

import java.awt.Graphics;

public class GameObject extends Game {
    
    double posX;
    double posY;
    double speed;
    
    //Constructor
    GameObject() {
        //
        posX = 400;
        posY = 300;
        speed = 200;
    }
    
    @Override 
    void Update() {
        if (Input.moveLeft == true) {
            posX = posX - (dT * speed);
        }
        if (Input.moveRight == true) {
            posX = posX + (dT * speed);
        }
        if (Input.moveUp == true) {
            posY = posY - (dT * speed);
        }
        if (Input.moveDown == true) {
            posY = posY + (dT * speed);
        }
    }
    
    @Override
    void Draw(Graphics g) {
        g.drawString("object", (int)(posX * factorX), (int)(posY * factorY));
    }
    
}


Tipkovnica (Input.java)
package vshooter;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class Input implements KeyListener {

    static boolean moveLeft;
    static boolean moveRight;
    static boolean moveUp;
    static boolean moveDown;
    static boolean fireP;
    static boolean fireS;
    
    //Constructor
    Input() {
        //initialization
        moveLeft = false;
        moveRight = false;
        moveUp = false;
        moveDown = false;
        fireP = false;
        fireS = false;
    }
    
    @Override
    public void keyTyped(KeyEvent e) {
        //not implemented
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == Settings.moveLeft) {
            moveLeft = true;
        }
        if (e.getKeyCode() == Settings.moveRight) {
            moveRight = true;
        }
        if (e.getKeyCode() == Settings.moveUp) {
            moveUp = true;
        }
        if (e.getKeyCode() == Settings.moveDown) {
            moveDown = true;
        }
        if (e.getKeyCode() == Settings.fireP) {
            fireP = true;
        }
        if (e.getKeyCode() == Settings.fireS) {
            fireS = true;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() == Settings.moveLeft) {
            moveLeft = false;
        }
        if (e.getKeyCode() == Settings.moveRight) {
            moveRight = false;
        }
        if (e.getKeyCode() == Settings.moveUp) {
            moveUp = false;
        }
        if (e.getKeyCode() == Settings.moveDown) {
            moveDown = false;
        }
        if (e.getKeyCode() == Settings.fireP) {
            fireP = false;
        }
        if (e.getKeyCode() == Settings.fireS) {
            fireS = false;
        }
    }
    
}


Branje nastavitev iz datoteke (Settings.java)
package vshooter;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class Settings {
    
    static int moveLeft;
    static int moveRight;
    static int moveUp;
    static int moveDown;
    static int fireP;   //fire primary
    static int fireS;   //fire secondary
    
    static boolean Load() {
        Properties prop = new Properties();
        //test for getting game.properties debug location
        //System.out.println(System.getProperty("user.dir"));
        try {
            //load a properties file
            prop.load(new FileInputStream("game.properties"));
            //get the property values
            moveLeft = Integer.parseInt(prop.getProperty("KeyLeft"));
            moveRight = Integer.parseInt(prop.getProperty("KeyRight"));
            moveUp = Integer.parseInt(prop.getProperty("KeyUp"));
            moveDown = Integer.parseInt(prop.getProperty("KeyDown"));
            fireP = Integer.parseInt(prop.getProperty("KeyFirePrimary"));
            fireS = Integer.parseInt(prop.getProperty("KeyFireSecondary"));
            return true;
    	}
        catch (IOException ex) {
            System.out.println("Error loading game.properties file.");
            return false;
        }
    }
}

Arto ::

Jaz sem se enkrat že malo igral s temi stvarmi, pa ti za javo priporočam JGame framework, je precej enostaven in ima spisanih večino stvari, ki jih boš potreboval za tako igro, pa tudi dokumentacija je kar kul. Razen če hočeš res vse iz nule.

PecenkA ::

Hočem vse iz nule, da se čim več naučim zraven.

Še eno vprašanje. Trenutno je GameObject dedovan iz Game. Glede na to, da bodo potem vsi ostali dedovani iz GameObject ali bi bilo bolje, da bi GameObject zastavil iz nule brez dedovanja iz Game, da nimajo potem nepotrebnega balasta zraven.

Arto ::

Ja jaz bi dal GameObject posebej, ker v bistvu ne deli ničesar z Game. Mogoče si lahko vseeno pogledaš vsaj dokumentacijo JGame, če ti zmanjka idej kako realizirat stvari, samo vidim, da maš itak že praktično enako zastavljeno :)

_Dormage_ ::

Zgleda lepo..
Ne razumet narobe, ampak me samo zanima ali obstaja razlog zakaj v vrtici
cT = (double)System.nanoTime() / 1000000000;

rabiš nanoTime in ga pol pretvarjaš v sekunde?

Kaj je razlika, če narediš
System.currentTimeMillis()/1000


Kakšna bo pa grafika? (Največ dela po mojih izkušnjah)

Arto ::

Aja saj res, za grafiko je najbolje da si narediš nek sprite sistem (se pravi različni farme-i v eni sliki, v nekakšnem koordinatnem sistemu).

PecenkA ::

@_Dormage_
System.nanoTime() vrne čas v najnatančnejšega možnega timerja v sistemu. Pri večini sistemov danes je natančen na kakšno mikrosekundo. Lahko bi naredil tudi s System.currentTimeMillis(), natančnost 10-15 ms je dovolj dobra za moje namene. Sem pa nekje bral, da se uporabi najboljši možni timer (sourca ne vem več).

Kar se grafike tiče, bo vse narejeno z Graphics.drawPolygon(). En objekt bo lahko sestavljen iz več poligonov različnih barv. Tudi collision detection je v tem primeru dokaj "enostaven". V planu je tudi editor objektov in stopenj.

Zgodovina sprememb…

  • spremenil: PecenkA ()

_Dormage_ ::

Če se boš lotu kake lepe grafike vsekakor spiši svoj Animation class, ki bo sfural animacije namesto tebe..
Teh stvari se dokaj hitro nabere.
Pa poglej si kak particle engine za eksplozije in efekte.
Enkrat ko usposobiš enega se začne zabava :))


EDIT:
Si me prehitel tako, da je zgornji text void.
Hvala za pojasnilo, ampak kot si že sam povedal take natančnosti ne potrebuješ za igro.

Zgodovina sprememb…

PecenkA ::

Sem našel odličen tutorial za Separate axis teorem za collision detection če koga zanima slučajno. http://www.codezealot.org/archives/55. Vodi pa še do enega prav tako odličnega.

MajorM ::

Odlična razlaga! Hvala PecenkA.

PecenkA ::

GameObject sem potem predelal, da ne deduje iz Game. Zaenkrat kaže, da bo vsaj v enostavni obliki zadeva špilala, ampak dokler ne bom kakšen mesec ali deset v razvoju ne morem vedeti. Na hitro par screenshotov testa, da se vidi kakšen stil grafike bo. Ne bo nobenih pobarvanih površin ali česa podobnega. Samo barvasti poligoni. Sem dodal random ozadje na level (malo sneži :)), da imam vsaj občutek, da se premikam, to je pa to.




Zgodovina sprememb…

  • spremenil: PecenkA ()

PecenkA ::

Sem preuredil zadevo tako, da je sedaj grafika uporablja Path2D.Double(). Sem prešaltal, ker sem mnogo lažje naredil collision detection z Area.intersect. Sicer je neučinkovito, ker moram pretvarjati Path2D v Area, samo za moje namene bo ok. Prav tako za izris namesto Graphics sedaj skrbi Graphics2D. Transformacije objektov sem prepustil vgrajenem AffineTransform objektu. Samo vpišeš matriko in to je to. Sicer je narejena podpora šele za translate, scale in rotate me še čakata. Finaliziral sem tudi format datoteke za objekte (videz).

Lista stvari, ki se jih bom lotil v kratkem:
- level loader + struktura datoteke z levelom
- dizajn orožij in objektov ker imam trenutno samo 4 testne
- dizajn testnega levela
- manager za zvočne efekte

Če ima kdo čas, lahko izriše kakšen objekt (malo lahko sanjam :)). Prilagam sliko za občutek, kaj imam v mislih, pa da se vidi omejitve. Objekt je lahko sestavljen iz poligonov različnih barv. Glej playerja.

Tudi kakšen nasvet glede česarkoli bi bil dobrodošel.



Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Keylogger

Oddelek: Programska oprema
352493 (1220) Blisk
»

Java script -> Navigacija s smernimi tipkami

Oddelek: Programiranje
12825 (577) tadejp81
»

[C#]Analogna ura

Oddelek: Programiranje
152581 (2218) cekr
»

[Silverlight 4] Omejeno premikanje elementov v canvasu

Oddelek: Programiranje
111123 (1003) xordie
»

Collision detection

Oddelek: Programiranje
81791 (1543) Senitel

Več podobnih tem