I am drawing on screen but what is drawn doesn't match where the mouse is. I am already using unproject to change screen cords to world cords. I am using fill viewport, I think the drawing is not scaled up to current screen size maybe?
public void setPoint(float x , float y) {
mPoints.get(currentPointIndex).set(x,y,0);
if (x != 0 && y != 0) {
getCamera().unproject(mPoints.get(currentPointIndex));
}
}
public void render(float delta) {
super.render(delta);
for(int i=0; i < maxPoints-1; i++) {
Vector3 pnt = mPoints.get(i);
Vector3 lastPnt = null;
if(i>0) lastPnt = mPoints.get(i-1);
if(pnt.x == 0 && pnt.y == 0) continue;
Vector3 pnt2 = mPoints.get(i+1);
if(pnt2.x == 0 && pnt2.y == 0) continue;
drawLine(sb,pnt,pnt2,lineWidth,lineTex,colors.get(i));
}
}
public UiScreen(WriteGame game, ScreenType screenType) {
super(game, screenType);
FitViewport sc = new FitViewport(LAYOUT_HEIGHT,LAYOUT_HEIGHT);
//sc.update(LAYOUT_HEIGHT,LAYOUT_HEIGHT,true);
mStage = new Stage(sc);
mStageCamera = new OrthographicCamera();
sc.setCamera(mStageCamera);
mInputMultiplexer = new InputMultiplexer();
mInputMultiplexer.addProcessor(mStage);
mGame = game;
}
Related
I'm trying to understand game-creation in Android. Therefore I try to program a simple TicTacToe without using buttons or layout files. Instead I want to only use bitmaps.
My Problem is that I can create the board, toggle the "X" and "O" symbol correctly, but my onDraw() only draws 2 symbols simultanously at max and I dont quite understand why or how to solve this.
public class GameScreen extends View {
List<TicTacToeSymbol> symbolList = new ArrayList<>();
float posX;
float posY;
int displayWidth;
int displayHeight;
Bitmap background;
Bitmap bitmapX;
Bitmap bitmapO;
Rect dst = new Rect();
boolean touched = false;
TicTacToeSymbol currentSymbol;
TicTacToeSymbol symbolX;
TicTacToeSymbol symbolO;
Grid grid = new Grid();
// Declaring the coordinates for the colums and rows
int ZERO_COLUMN_X = 0;
int FIRST_COLUMN_X = 480;
int SECOND_COLUMN_X = 910;
int THIRD_COLUMN_X = 1425;
(...)
int centerX = 0;
int centerY = 0;
public GameScreen(Context context) {
super(context);
try {
AssetManager assetManager = context.getAssets();
InputStream inputStream = assetManager.open("tictactoegrid.jpg");
background = BitmapFactory.decodeStream(inputStream);
inputStream = assetManager.open("X.png");
bitmapX = BitmapFactory.decodeStream(inputStream);
inputStream = assetManager.open("O.png");
bitmapO = BitmapFactory.decodeStream(inputStream);
inputStream.close();
// I create only 2 symbols, which might be the problem
symbolX = new TicTacToeSymbol(0, 0, 1);
symbolX.setBitmap(bitmapX);
symbolO = new TicTacToeSymbol(0, 0, 2);
symbolO.setBitmap(bitmapO);
setCurrentSymbol(symbolX, 1);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
Display display = this.getDisplay();
Point size = new Point();
display.getSize(size);
displayWidth = size.x;
displayHeight = size.y;
}
public void toggleCurrentSymbol() {
if (currentSymbol == symbolX) {
currentSymbol = symbolO;
} else {
currentSymbol = symbolX;
}
}
public void setCurrentSymbol(TicTacToeSymbol ticTacToeSymbol, int type) {
this.currentSymbol = ticTacToeSymbol;
if (type == 1) {
currentSymbol.setType(1);
} else
currentSymbol.setType(2);
}
public void setCoordinatesCurrentSymbol(int centerX, int centerY) {
currentSymbol.setPosX(centerX);
currentSymbol.setPosY(centerY);
}
#Override
public void onDraw(Canvas canvas) {
dst.set(0, 0, displayWidth, displayHeight - 200);
canvas.drawBitmap(background, null, dst, null);
if (touched) {
// Checking where the user has clicked
// First row
if (posX >= ZERO_COLUMN_X && posX <= FIRST_COLUMN_X
&& posY > ZERO_ROW_Y && posY < FIRST_ROW_Y) {
centerX = FIRST_CENTER_X;
centerY = FIRST_CENTER_Y;
setCoordinatesCurrentSymbol(centerX, centerY);
grid.placeSignInGrid(0, 0, currentSymbol);
toggleCurrentSymbol();
}
if (posX > FIRST_COLUMN_X && posX <= SECOND_COLUMN_X
&& posY > ZERO_ROW_Y && posY < FIRST_ROW_Y) {
centerX = SECOND_CENTER_X;
centerY = FIRST_CENTER_Y;
setCoordinatesCurrentSymbol(centerX, centerY);
grid.placeSignInGrid(1, 0, currentSymbol);
toggleCurrentSymbol();
}
(...)
}
// Go through the grid, get the symbol at the position and add it to the list of symbols
for (int i = 0; i < Grid.GRID_SIZE; i++) {
for (int j = 0; j < Grid.GRID_SIZE; j++) {
if (grid.getSymbolAtField(i, j) != null) {
if (!symbolList.contains(grid.getSymbolAtField(i, j))) {
symbolList.add(grid.getSymbolAtField(i, j));
}
}
}
}
// Draw every symbol in the list.
for (TicTacToeSymbol ttts : symbolList) {
canvas.drawBitmap(ttts.getBitmap(), ttts.getPosX(), ttts.getPosY(), null);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
touched = true;
posX = event.getX();
posY = event.getY();
invalidate();
return true;
}
return false;
}
}
I create only 2 TicTacToeSymbols, namely symbolXand symbolO. Therefore the symbolList only contains these 2 and draws only those 2.
But how can I draw the same symbol several times? Else I would have to create 9 X-Symbols including the bitmap and 9 O-Symbols to cover all grid-fields with the possible symbols. This would seem wrong / not very elegant?
So how can I draw my 2 symbols several times at the correct positions?
I've looked into several posts like this but could not derive a solution for my problem:
Draw multiple times from a single bitmap on a canvas ... this positions the bitmaps randomly, but I want my symbols on specific positions.
I'm pretty new in LibGDX and Android Studio.
I'm trying to create a simple animation using 8 png files, the animation happens but it's so fast and unrealistic.
Is there a way to put a delay between frames?.
Thanks.
public class Runningrabbit extends ApplicationAdapter {
SpriteBatch batch;
Texture background;
Texture[] rabbits;
int rabbitState = 0;
float stateTime;
#Override
public void create () {
batch = new SpriteBatch();
background = new Texture("back.png");
rabbits = new Texture[8];
rabbits[0] = new Texture("rabbit1.png");
rabbits[1] = new Texture("rabbit2.png");
rabbits[2] = new Texture("rabbit3.png");
rabbits[3] = new Texture("rabbit4.png");
rabbits[4] = new Texture("rabbit5.png");
rabbits[5] = new Texture("rabbit6.png");
rabbits[6] = new Texture("rabbit7.png");
rabbits[7] = new Texture("rabbit8.png");
stateTime = 0f;
}
#Override
public void render () {
if (rabbitState == 0) {
rabbitState = 1;
} else if (rabbitState == 1) {
rabbitState = 2;
} else if (rabbitState == 2) {
rabbitState = 3;
} else if (rabbitState == 3) {
rabbitState = 4;
} else if (rabbitState == 4) {
rabbitState = 5;
} else if (rabbitState == 5) {
rabbitState = 6;
} else if (rabbitState == 6) {
rabbitState = 7;
} else if (rabbitState == 7) {
rabbitState = 0;
}
batch.begin();
batch.draw(background, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.draw(rabbits[rabbitState], 200, 200);
batch.end();
}
}
You need to have the changing of the animation's state depend on time.
for example,
float accumulator = 0f;
...
public void render(){
float dt = Gdx.graphics.deltaTime(); //dt is the number of seconds that have passed in between each frame
accumulator += dt;
if(accumulator > 1)//one second has passed{
rabbitState++;
accumulator -= 1;
}
...
now, the animation will move forward once every second (which is painfully slow, but you can adjust then number).
Beyond your question, two things that I noticed looking through your code are:
You're making a new texture for each frame. Don't do this, have a texture with all the frames and make texture regions. There's no point in using a SpriteBatch if it needs to swap textures every single draw call.
There's an animation class in LibGDX as someone else has pointed out, it'll save you a lot of hassle to just use it.
You're manually changing the state with if statements when you just have to increment your index.
In one of my Android applications (Made with Unity), I would like to move the camera by scrolling with finger on the screen and simultaneously not detect hit, when I touch on any object during scrolling. My problem is that when I want to scroll down the camera with my finger, it firstly also detects hits with the objects. I have one script which is attached to Main Camera.
Here's the code for better understanding.
//Update function for scrolling and detecting touch.
//Do not want to detect touch on objects when scrolling.
void Update () {
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began) {
checkTouch(Input.GetTouch(0).position);
}
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved) {
Vector2 touchDeltaPosition = Input.GetTouch(0).deltaPosition;
transform.Translate(0, -touchDeltaPosition.y * Time.deltaTime, 0);
transform.position = new Vector3(0, Mathf.Clamp(transform.position.y, -30, 0), -10);
}
}
void checkTouch(Vector3 pos){
Vector3 wp = Camera.main.ScreenToWorldPoint (pos);
Vector2 touchpos = new Vector2 (wp.x, wp.y);
hit = Physics2D.OverlapPoint (touchpos);
if (hit) {
//Debug.Log (hit.transform.gameObject.name);
//hit.transform.gameObject.SendMessage ("Clicked", null, SendMessageOptions.DontRequireReceiver);
if (hit.transform.gameObject.tag == "item"){
//do something
}
}
}
I think you can try use something like this
void Update()
{
if (Input.touchCount <= 0)
return;
bool lMove = false;
if (Input.GetTouch(0).phase == TouchPhase.Moved)
{
Debug.Log("Touch phase = Moved");
lMove = true;
Vector2 touchDeltaPosition = Input.GetTouch(0).deltaPosition;
transform.Translate(0, -touchDeltaPosition.y * Time.deltaTime, 0);
transform.position = new Vector3(0, Mathf.Clamp(transform.position.y, -30, 0), -10);
}
if (Input.GetTouch(0).phase == TouchPhase.Ended)
{
Debug.Log("Touch phase = Ended");
if (!lMove)
{
//onClick
checkTouch(Input.GetTouch(0).position);
}
}
}
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class LineDirDetector: MonoBehaviour {
public Text texto01;
//inside class
Vector2 firstPressPos;
Vector2 secondPressPos;
Vector2 currentSwipe;
void Update()
{
Swipe();
}
public void Swipe() {
if (Input.touches.Length > 0) {
Touch t = Input.GetTouch(0);
if (t.phase == TouchPhase.Began) {
//save began touch 2d point
firstPressPos = new Vector2(t.position.x, t.position.y);
}
if (t.phase == TouchPhase.Ended) {
//save ended touch 2d point
secondPressPos = new Vector2(t.position.x, t.position.y);
//create vector from the two points
currentSwipe = new Vector3(secondPressPos.x - firstPressPos.x, secondPressPos.y - firstPressPos.y);
//normalize the 2d vector
currentSwipe.Normalize();
//swipe upwards
if (currentSwipe.y > 0 && currentSwipe.x > -0.5 f && currentSwipe.x < 0.5 f) {
Debug.Log("up swipe");
texto01.text = "ARRIBA";
}
//swipe down
if (currentSwipe.y < 0 && currentSwipe.x > -0.5 f && currentSwipe.x < 0.5 f) {
Debug.Log("down swipe");
texto01.text = "ABAJO";
}
//swipe left
if (currentSwipe.x < 0 && currentSwipe.y > -0.5 f && currentSwipe.y < 0.5 f) {
Debug.Log("left swipe");
texto01.text = "IZQUIERDA";
}
//swipe right
if (currentSwipe.x > 0 && currentSwipe.y > -0.5 f && currentSwipe.y < 0.5 f) {
Debug.Log("right swipe");
texto01.text = "DERECHA";
}
}
}
}
}
Here is my problem , i have a camera that i move right , left , down and up with Touch in android device , and i have a gui button who shows me a text when i double tap on it. The problem that when i touch the gui button , the camera move. I want when i touch the gui button , the camera stops moving and when i touch anywhere else in the screen the camera moves.
Here is my code:
public float tapSpeed = 0.5f;
private float lastTapTime = 0;
public Touch touch;
public Vector2 startPos;
public Vector2 endPos;
public bool fingerHold = false;
private float CameraYLimitUp;
private float CameraYLimitDown;
private float CameraXLimitRight;
private float CameraXLimitLeft;
public GUIText guiTextTap;
void Awake()
{
CameraYLimitUp = 0;
CameraYLimitDown = 27;
CameraXLimitRight = -15;
CameraXLimitLeft = 22;
}
void Update()
{
// Camera moves left right up down with touch
if (Input.touchCount > 0)
{
touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began)
{
startPos = touch.position;
fingerHold = true;
print("touch began");
}
else if (touch.phase == TouchPhase.Moved)
{
endPos = touch.position;
}
else if (touch.phase == TouchPhase.Ended)
{
fingerHold = false;
print("touch end");
}
}
if (fingerHold)
{
float deltaX = endPos.x - startPos.x;
float deltaY = endPos.y - startPos.y;
bool horizontal = false;
if (Mathf.Abs(deltaX) > Mathf.Abs(deltaY))
horizontal = true;
if (horizontal)
{
if (deltaX < 0 && transform.position.x < CameraXLimitLeft)
transform.Translate(Vector3.left * Time.deltaTime * 20);
else if (deltaX > 0 && transform.position.x > CameraXLimitRight)
transform.Translate(Vector3.right * Time.deltaTime * 20);
}
else
{
if (deltaY < 0 && transform.position.y < CameraYLimitDown)
transform.Translate(Vector3.down * Time.deltaTime * 20);
else if (deltaY > 0 && transform.position.y > CameraYLimitUp)
transform.Translate(Vector3.up * Time.deltaTime * 20);
}
}
}
void OnGUI()
{
if (GUI.Button(new Rect(480 , 289.5f , 100, 100), "GUI Test"))
{
if ((Time.time - lastTapTime) < tapSpeed)
{
Debug.Log("Gui Button Taped");
guiTextTap.text = "Gui Button Taped";
}
lastTapTime = Time.time;
}
}
I Uploaded my project , you can find it here : https://mega.co.nz/#!0EkHQRDI!yDcUfJR_B5poXokku7fExOc-NtlDyYDeTCaBiAePzMs
Thanks a lot for your help
Checking the GUI hot control id would solve that issue, i.e. if the value of GUIUtility.hotControl is greater than 0, it means that the user holds down a button. Hence, you could simply modify your if statement as below to bypass the camera movement when the user presses down the button:
void Update()
{
...
...
// Check additionally if the GUI button is currently free
if (GUIUtility.hotControl == 0 && fingerHold)
{
...
...
}
}
I am trying to rotate floor using Input.acceleration. I want to rotate floor around the point where player is standing and to limit my rotations at certain angles also stop at 0 if Input.acceleration is close to zero. considering that i'm newbie at game programming I've came up with this code:
using UnityEngine;
using System.Collections;
public class Tilt : MonoBehaviour {
public float maxRotationAngle = 350; // max rotation right
public float minRotationAngle = 10; // max rotation left
public float rotationSpeed = 20; //rotation speed
public Transform rotateAround; //rotation point
private bool stopRotation = false; //if this is true rotation stops
private int stopDir; //direction where rotation stops -1 equals left 0 center 1 right
void Update () {
int tiltDir = 0; //input tilt direction
float accel = Input.acceleration.x; //input tilt value
float currentRotation = transform.eulerAngles.z; //current rotation
//set rotation direction
if (accel > 0) {
tiltDir = 1;
}else if (accel < 0){
tiltDir = -1;
}
//stop rotation left
if (!stopRotation && (currentRotation < maxRotationAngle && currentRotation > 270)) {
stopRotation = true;
stopDir = -1;
}
//stop rotation right
if (!stopRotation && (currentRotation > minRotationAngle && currentRotation < 270)) {
stopRotation = true;
stopDir = 1;
}
//allow rotation right
if (stopRotation && stopDir < 0 && Input.acceleration.x > 0) {
stopRotation = false;
}
//allow rotation left
if (stopRotation && stopDir > 0 && Input.acceleration.x < 0) {
stopRotation = false;
}
//stop rotation center
if(!stopRotation && currentRotation < 0.2 || (currentRotation > 359.8 && currentRotation < 360)){
if(accel > -0.1 && accel < 0.1){
stopRotation = true;
stopDir = 0;
}
}
//allow rotation from center
if(stopRotation && stopDir == 0 && (accel < -0.1 || accel > 0.1)){
stopRotation = false;
}
//apply rotation
if(!stopRotation){
transform.RotateAround(rotateAround.position, new Vector3(0, 0, tiltDir), rotationSpeed * Mathf.Abs(accel) * Time.deltaTime);
}
}
}
This is working but this approach is not exact and i think there are cheaper ways of doing this. So Is there a better way?
I came up with this, which I think accomplishes what you wanted, although I may have misread your code. I've removed your magic number, changed the angles to map between -180 and 180 and renamed your variables to have full names for better maintainability.
public float maxRotationAngle = 170;
public float minRotationAngle = -170;
public float minimumAcceleration = 0.1f;
public float rotationSpeed = 20;
public Transform rotateAroundTransform;
void Update ()
{
float deltaAcceleration = Mathf.Abs(Input.acceleration.x);
float currentRotation = transform.eulerAngles.z;
//stop rotation outside of angle range and motion range
if (currentRotation > minRotationAngle &&
currentRotation < maxRotationAngle &&
deltaAcceleration < minimumAcceleration)
{
//set rotation direction
int tiltDirection = Input.acceleration.x > 0 ? 1 : -1;
transform.RotateAround(rotateAroundTransform.position, new Vector3(0, 0, tiltDirection), rotationSpeed * deltaAcceleration * Time.deltaTime);
}
}
Hope that helps!