Strategie Spiel entwickeln

  • Antworten:16
  • OffenNicht stickyNicht beantwortet
  • Forum-Beiträge: 13

07.05.2016, 18:48:23 via Website

Hey,

Mein Plan ist es, ein kleines Aufbauspiel zu programmieren ohne viel Schnickschnack.
Derzeit funktioniert es gut, aber..
Wenn ich z.B ein Gebäude verschieben will, (was ich auch kann via Drag'n'Drop) und es irgendwo geplant hinmachen will, z.B im Raster geht das nicht. Wie kann ich Einstellen, das wenn z.B Das Gebäude bzw das Bild 1-5 px entfernt ist vom einen Rasterpunkt auf den Punkt "springt"? Ist das und möglich und wenn ja, wie?
Und wie erstelle ich ein Raster? Soll ich dies mit den Layouts erledigen oder immer einzelne Bilder? (was aber warscheinlich sehr viel Speicher frisst)

Ich freue mich über jede Hilfe.

— geändert am 18.05.2016, 21:22:45

Antworten
  • Forum-Beiträge: 82

18.05.2016, 11:55:32 via Website

Aufbauspiel? Meinst du so ähnlich wie die Strategiespiele wo man zuerst Gebäude bauen muss in denen man dann z.B. neue Einheiten produzieren kann? Gebäude sind dabei auf Bitmaps dargestellt oder wie? In Java könnte man einfach prüfen ob die linke obere Ecke in der Nähe eines Rasterpunktes liegt und in so einem Fall die Position des Bitmaps passend setzen.

Antworten
  • Forum-Beiträge: 13

18.05.2016, 16:51:50 via Website

Ja so meine ich das.
Folgender Fall:
Spieler spielt im Tutorial. Im Tutorial wird gezeigt, wie er ein Gebäude aufbaut und es platziert. Er soll ein Rathaus aufbauen und es platzieren. Dem Spieler wird vorgegeben, wo er das Rathaus platzieren sollte, das ist ein grünes Feld. Sobald das Rathaus in die Nähe des grünen Feldes kommt, soll es einrasten.

Die Gebäude werden als einziges Bild dargestellt, z.B eine .png.

mfG
smaxxx

Antworten
  • Forum-Beiträge: 82

18.05.2016, 17:29:34 via Website

Ich habe eben eine kleine APP geschrieben, die etwas primitiv aber doch richtig das Einrasten eines Bitmaps auf eine bestimmte Position implementiert. mainIV ist dabei ein ImageView mit folgendem Layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center">

    <ImageView
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:id="@+id/mainIV"/>

</LinearLayout>

MainActivity:

package com.mycompany.myapp;

import android.app.*;
import android.content.*;
import android.graphics.*;
import android.os.*;
import android.view.*;
import android.view.View.*;
import android.widget.*;

public class MainActivity extends Activity 
implements
OnTouchListener
{

    private ImageView iv;
    private float posX=100,posY=200;
    private boolean eingerastet;
    //Einrastedistanz
    private float eD=50;
    @Override
    public boolean onTouch(View v, MotionEvent e)
    {
        float x=e.getX();
        float y=e.getY();
        eingerastet=Math.abs(x - posX) < eD && Math.abs(y - posY) < eD;
        if (eingerastet)
        {

            b.setX(posX);
            b.setY(posY);
        }
        else
        {
            b.setX(x);
            b.setY(y);
        }
        iv.setImageBitmap(getBitmap(v.getWidth(), v.getHeight()));
        return true;
    }
    private Bitmap getBitmap(int w, int h)
    {
        Bitmap.Config conf = Bitmap.Config.ARGB_8888; // see other conf types
        Bitmap bmp = Bitmap.createBitmap(w, h, conf); // this creates a MUTABLE bitmap
        Canvas canvas = new Canvas(bmp);
        canvas.drawBitmap(position, posX, posY, null);
        canvas.drawBitmap(b.getB(), b.getX(), b.getY(), null);
        return bmp;
    }
    public class Building
    {
        public Building(Context c)
        {
            b = BitmapFactory.decodeResource(c.getResources(),
                                             android.R.drawable.alert_light_frame);
        }
        private Bitmap b;

        public void setY(float y)
        {
            Y = y;
        }

        public float getY()
        {
            return Y;
        }

        public void setX(float x)
        {
            X = x;
        }

        public float getX()
        {
            return X;
        }
        public Bitmap getB()
        {
            return b;
        }
        float X;
        float Y;

    }
    Building b;
    Bitmap position;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        iv = (ImageView)findViewById(R.id.mainIV);
        iv.setOnTouchListener(this);
        b = new Building(this);
        position = BitmapFactory.decodeResource(getResources(),
                                                android.R.drawable.alert_dark_frame);


    }
}

— geändert am 18.05.2016, 17:30:26

smaxxx

Antworten
  • Forum-Beiträge: 13

18.05.2016, 18:37:03 via Website

Habs mir jetzt mal 3 mal durch gelesen und hab jetzt es kapiert wie es funktioniert etc.

Aber jetzt kommt mir eine zweite Frage auf:
Gibts das irgendwo so zu lesen in ein Buch oder wie hast du das gelernt?

Antworten
  • Forum-Beiträge: 82

18.05.2016, 19:01:41 via Website

eingerastet=Math.abs(x - posX) < eD && Math.abs(y - posY) < eD;

Diese Zeile ist entscheidend.

x und y ist die Position des Fingers.

posX und posY soll die gewünschte Position des Gebäudes sein.

x-posX und y-posY
Sind die Entfernungen* (Unterschiede) des Fingers von posX posY.

Math.abs berechnet den Betrag einer Zahl (also das Vorzeichen weg), hier wichtig, damit das Gebäude auch von Hinten oder von oben einrastet.

( * ) Eigentlich sind das Komponenten des Vektors zwischen Punkt P(posX|posY) und Punkt F(x,y). Besser wäre es die Länge dieses Vektors auszurechnen, so könnte man innerhalb eines Kreisses einrasten. Zur Zeit wird eingerastet, wenn der Finger innerhalb eines Quadrats mit Seitenlänge 2*eD und Mittelpunkt M(posX,posY) sich befindet.

— geändert am 18.05.2016, 19:03:57

Antworten
  • Forum-Beiträge: 82

18.05.2016, 19:14:31 via Website

Hier eine Version mit beliebieg vielen Gebäuden und so:
main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <Button
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:text="AddBuilding"
        android:onClick="onClick"
        android:id="@+id/mainBADDB"/>

    <ImageView
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:id="@+id/mainIV"/>

</LinearLayout>

MainActivity.java:

package com.mycompany.myapp;

import android.app.*;
import android.content.*;
import android.graphics.*;
import android.os.*;
import android.view.*;
import android.view.View.*;
import android.widget.*;
import java.util.*;

public class MainActivity extends Activity 
implements
OnTouchListener
{

    private ImageView iv;
    private float posX=100,posY=200;
    private boolean eingerastet;
    //Einrastedistanz
    private float eD=50;
    @Override
    public boolean onTouch(View v, MotionEvent e)
    {   
        float x=e.getX();
        float y=e.getY();
        if(e.getAction()==MotionEvent.ACTION_DOWN)
            for (int i=0;i < bl.size();i++)
            {
                Building b=bl.get(i);
                if(x>b.getX()&&x<b.getX()+b.getB().getWidth()&&
                    y>b.getY()&&y<b.getY()+b.getB().getHeight()
                )sB=b;


            }
        if (sB != null)
        {
            eingerastet = Math.abs(sB.getX() - sB.posX) < eD && Math.abs(sB.getY() - sB.posY) < eD;


            if (eingerastet)
            {
                sB.setX(sB.posX);
                sB.setY(sB.posY);
            }
            else
            {
                sB.setX(x);
                sB.setY(y - sB.b.getHeight());
            }
        }
        iv.setImageBitmap(getBitmap(v.getWidth(), v.getHeight()));
        return true;
    }
    Building sB;
    private Bitmap getBitmap(int w, int h)
    {
        Bitmap.Config conf = Bitmap.Config.ARGB_8888; // see other conf types
        Bitmap bmp = Bitmap.createBitmap(w, h, conf); // this creates a MUTABLE bitmap
        Canvas canvas = new Canvas(bmp);
        for (int i=0;i < bl.size();i++)
        {
            Building b=bl.get(i);
            if (!b.isFixed())
                canvas.drawBitmap(b.getPosB(), b.posX, b.posY, null);
            canvas.drawBitmap(b.getB(), b.getX(), b.getY(), null);
        }
        return bmp;
    }
    public class Building
    {
        private boolean fixed;
        public float posX,posY;
        public Bitmap posB;
        public Building(Context c)
        {
            b = BitmapFactory.decodeResource(c.getResources(),
                                             android.R.drawable.alert_light_frame);
            posB = BitmapFactory.decodeResource(c.getResources(),
                                                android.R.drawable.alert_dark_frame);
        }
        private Bitmap b;

        public void setPosY(int nextInt)
        {
            posY = nextInt;
        }

        public void setPosX(int nextInt)
        {
            posX = nextInt;
        }

        public Bitmap getPosB()
        {
            return posB;
        }

        public void setFixed(boolean fixed)
        {
            this.fixed = fixed;
        }

        public boolean isFixed()
        {
            return fixed;
        }

        public void setY(float y)
        {
            Y = y;
        }

        public float getY()
        {
            return Y;
        }

        public void setX(float x)
        {
            X = x;
        }

        public float getX()
        {
            return X;
        }
        public Bitmap getB()
        {
            return b;
        }
        float X;
        float Y;

    }
    ArrayList<Building> bl;
    Bitmap position;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        iv = (ImageView)findViewById(R.id.mainIV);
        iv.setOnTouchListener(this);
        bl = new ArrayList<Building>();
        position = BitmapFactory.decodeResource(getResources(),
                                                android.R.drawable.alert_dark_frame);


    }
    public void onClick(View v)
    {
        Building b=new Building(this);
        b.setX(iv.getWidth() / 2 - b.b.getWidth() / 2);
        b.setY(iv.getHeight() / 2 - b.b.getHeight() / 2);
        b.setPosX(new Random().nextInt(iv.getWidth() - b.b.getWidth()));
        b.setPosY(new Random().nextInt(iv.getHeight() - b.b.getHeight()));
        bl.add(b);
        iv.setImageBitmap(getBitmap(iv.getWidth(), iv.getHeight()));
    }
}

— geändert am 18.05.2016, 19:24:43

Antworten
  • Forum-Beiträge: 13

18.05.2016, 19:43:56 via Website

Ja gerne, bin noch ein großer Anfänger in Java bzw Android Programmierung. Jede Hilfe ist hilfreich :D
Frage: if(e.getAction()==MotionEvent.ACTION_DOWN) <- Ist das der Code für eine Geste?

Und vielen Dank für deine Hilfe und deiner Geduld das du mir hilfst.

Antworten
  • Forum-Beiträge: 82

18.05.2016, 19:53:06 via Website

e.getAction()==MotionEvent.ACTION_DOWN 

Dann, wenn der Finger den Bildschirm berührt. Wenn man den Bewegt dann ist

 e.getAction()==MotionEvent.ACTION_MOVE 

und wenn man wieder loslässt wird

e.getAction()==MotionEvent.ACTION_UP

Die "ACTION_MOVE" wird dabei ganz oft ausglöst während der Bewegung. Deshalb sieht man die Animation.

— geändert am 18.05.2016, 19:56:50

smaxxx

Antworten
  • Forum-Beiträge: 13

18.05.2016, 20:18:09 via Website

Okay ich hab jetzt mal den Code genommen und ihn getestet. Funktioniert super, sieht auch gut aus.

Und wenn ich jetzt z.B den schwarzen Rahmen bzw. Punkt vorsetzen will, wo er "spawnen" soll, soll ich einfach das random entfernen und die Position einsetzen?

Und was, wenn ich den nächsten Schwarzen Rahmen neben dem anderen schwarzen Rahmen setzen will, sobald er gespawnt wird?

  1. Frage:
    Seit wann programmierst du schon? Weil du hast wahrscheinlich sehr viel Erfahrung in Programmierung. Bist du schon lange dran oder kann auch so ein Anfänger wie ich das easy erlernen? :D

Antworten
  • Forum-Beiträge: 82

18.05.2016, 20:43:09 via Website

KA. Hab mit 15 angefangen C++ zu lernen.

Hab Mittlerweile Gebäudemenü und Einheiten implentiert. Gebäude haben ja float Koordinaten, sie könnten also auch hinter dem sichtbaren Bereich liegen. Dann muss man die Einheiten auswählen und los schicken können. Kollisionserkennung und so.

image

— geändert am 18.05.2016, 20:53:50

Antworten
  • Forum-Beiträge: 82

18.05.2016, 21:30:52 via Website

Cool: Man kann den Einheiten nun ein Ziel setzen
Die gebauen Einheiten bewegen sich nun aus der Kaserne zum Erscheinungspunkt.

image

Antworten
  • Forum-Beiträge: 13

19.05.2016, 14:53:31 via Website

Cool!
Und was, wenn ich ein Weg bzw Pfad bauen möchte, der aufgezogen werden kann? Also so:
Spieler kauft "Weg" er platziert es und drückt auf ein grünen Haken. Er kann jetzt ihn aufziehen nach rechts, links, oben und unten. Damit man nicht in Gebäude reinbauen kann, braucht es ebenfalls eine Kollisionserkennung.

Antworten
  • Forum-Beiträge: 82

19.05.2016, 16:58:26 via Website

Man muss dafür eine Map definieren. Z.B.

int[][] map=new int[breite][hoehe];

Wenn man nun ein Gebäude plaziert, setzt man alle Kästchen die das Gebäude belegt gleich 1.
Sagen wir nur ein Kästchen an der Position P(3|5):

map[3][5]=1;

Und beim nächstem Setzen eines Gebäudes checken:

if(map[x][y]==0)
{
// Gebäude kann gesetzt werden
}

— geändert am 19.05.2016, 17:30:07

smaxxx

Antworten

Empfohlene Artikel