How to render Sprites normally on rotated isometric tiles? LIBGDX - matrix

i was using this tutorial to make an isometric Map from normal Sprites:
http://www.badlogicgames.com/wordpress/?p=2032
I want to render a house on top of my floor tiles at position 0,0, but it looks like this:
http://gyazo.com/c7d5cd74829150c684cfa7b40c9fdfba
Here is my create() and render():
#Override
public void create () {
batch = new SpriteBatch();
img = new Texture(Gdx.files.internal("grass2d.jpg"));
//House
house = new Sprite(new Texture(Gdx.files.internal("mb_0004.png")));
house.setSize(2,2);
house.setPosition(0,0);
// Camera
cam = new OrthographicCamera(10,10*(Gdx.graphics.getHeight()/(float)Gdx.graphics.getWidth()));
cam.position.set(5,5,10);
cam.direction.set(-1,-1,-1);
cam.near = 1;
cam.far = 100;
//Matrices
//Matrix to rotate floor tiles
matrix.setToRotation(new Vector3(1,0,0), 90);
// Subject to change?
matrix2.setToRotation(new Vector3(0,1,0),45);
// populate Tiles
for(int z = 0; z < 100; z++) {
for(int x = 0; x < 100; x++) {
sprites[x][z] = new Sprite(img);
sprites[x][z].setPosition(x,z);
sprites[x][z].setSize(1, 1);
}
}
Gdx.input.setInputProcessor(this);
}
#Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
cam.update();
batch.setProjectionMatrix(cam.combined);
batch.setTransformMatrix(matrix);
batch.begin();
for(int z = 0; z < 100; z++) {
for(int x = 0; x < 100; x++) {
sprites[x][z].draw(batch);
}
}
batch.end();
batch.begin();
//batch.setTransformMatrix(matrix2);
house.draw(batch);
batch.end();
I did try to create another Matrix to transform it back, but then my coordinates are messed up. Hope you guys can help.

i was able to do it using TiledMap and a self written algorithm to detect wether or not a tile has been clicked and which one. I am able to place my house by mouse now and really like the result.
If anybody is interested, i will take some time to write a small tutorial.
Here is what it looks like at the moment:
Isometric Tiles

Related

Unity gun flipping

I'm making a top down shooter game and when I point my gun backwards, it is upside down. Here's my player script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public float moveSpeed = 5f;
public Rigidbody2D rb;
public Camera cam;
Vector2 movement;
Vector2 mousePos;
public GameObject crossHair;
public SpriteRenderer sr;
void Start() {
Cursor.visible = false;
}
// Update is called once per frame
void Update()
{
sr = GetComponent<SpriteRenderer>();
rb = GetComponent<Rigidbody2D>();
movement.x = Input.GetAxisRaw("Horizontal");
movement.y = Input.GetAxisRaw("Vertical");
mousePos = cam.ScreenToWorldPoint(Input.mousePosition);
crossHair.transform.position = new Vector2(mousePos.x, mousePos.y);
}
void FixedUpdate()
{
rb.velocity = new Vector2(movement.x, movement.y) * moveSpeed;
Vector3 lookDir = mousePos - rb.position;
lookDir.Normalize();
float angle = Mathf.Atan2(lookDir.y, lookDir.x) * Mathf.Rad2Deg;
rb.rotation = angle;
if (transform.position.y >= 6.4f) {
transform.position = new Vector2(transform.position.x, 6.4f);
}
if (transform.position.y <= -6.4f) {
transform.position = new Vector2(transform.position.x, -6.4f);
}
if (transform.position.x >= 11.9) {
transform.position = new Vector2(11.9f, transform.position.y);
}
if (transform.position.x <= -11.9) {
transform.position = new Vector2(-11.9f, transform.position.y);
}
float z = transform.rotation.eulerAngles.z;
if (z > 0 && z < 180 && !sr.flipX)
sr.flipX = true;
else if (z < 360 && z > 180 && sr.flipX)
sr.flipX = false;
}
void Flip(){
Vector3 Scaler = transform.localScale;
Scaler.y *= -1;
transform.localScale = Scaler;
}
}
I've searched a lot but I couldn't make it work. I tried with spriteRenderer but it doesn't work either. I really need help.(Btw my player rotates with the player)
Sounds to me like your system is just rotating the object without a second though for what direction it's facing. I imagine if you put an arrow or triangle pointing in the direction you like instead of a gun, it would look just fine.
So what I would do is the following:
if (the rotation is backwards)
render the sprite flipped vertically
else
render the sprite normally

Implementing circle progress bar in libGDX

I want to create a circle progress bar, that will look like this using libgdx library. For now on I've created simple horizontal progressbar using different Images as layers overlapping themselfs and one of them resizing to simulate progress. I found this example, how to draw circle progress bar, but I don't understand how to use this implementation and how can I handle it. The textureRegion in constructor is the progress indicator? and I could not find the method responsible to set the actual progress.
EDIT: I've made my solution basic on this implementation. I put 3 layers which overlapping themselfs and whenever the middle layer swipe's the progress is showed. But Ive have a problem: whenever I try to resize my ProgressCircle instance it move down below the background layer.
public class ProgressCircle extends Image {
public enum IntersectAt {
NONE, TOP, BOTTOM, LEFT, RIGHT;
}
TextureRegion texture;
PolygonSpriteBatch polyBatch;
Vector2 center;
Vector2 centerTop;
Vector2 leftTop;
Vector2 leftBottom;
Vector2 rightBottom;
Vector2 rightTop;
Vector2 progressPoint;
float[] fv;
IntersectAt intersectAt;
private float PROGRESS_WIDTH=0f;
private float PROGRESS_HEIGHT=0f;
private float posX,posY;
public ProgressCircle(TextureRegion region, PolygonSpriteBatch polyBatch,float width,float height,float posX,float posY) {
super(region);
PROGRESS_WIDTH=width;
PROGRESS_HEIGHT=height;
this.posX=posX;
this.posY=posY;
this.texture = region;
this.polyBatch = polyBatch;
center = new Vector2(this.getWidth() / 2, this.getHeight() / 2);
centerTop = new Vector2(this.getWidth() / 2, this.getHeight());
leftTop = new Vector2(0, this.getHeight());
leftBottom = new Vector2(0, 0);
rightBottom = new Vector2(this.getWidth(), 0);
rightTop = new Vector2(this.getWidth(), this.getHeight());
progressPoint = new Vector2(this.getWidth() / 2, this.getHeight() / 2);
setPercentage(0);
}
private Vector2 IntersectPoint(Vector2 line) {
Vector2 v = new Vector2();
boolean isIntersect;
//check top
isIntersect = Intersector.intersectSegments(leftTop, rightTop, center, line, v);
//check bottom
if (isIntersect) {
intersectAt = IntersectAt.TOP;
return v;
} else
isIntersect = Intersector.intersectSegments(leftBottom, rightBottom, center, line, v);
//check left
if (isIntersect) {
intersectAt = IntersectAt.BOTTOM;
return v;
} else isIntersect = Intersector.intersectSegments(leftTop, leftBottom, center, line, v);
//check bottom
if (isIntersect) {
intersectAt = IntersectAt.LEFT;
return v;
} else isIntersect = Intersector.intersectSegments(rightTop, rightBottom, center, line, v);
if (isIntersect) {
intersectAt = IntersectAt.RIGHT;
return v;
} else {
intersectAt = IntersectAt.NONE;
return null;
}
}
public void setPercentage(float percent) {
//100 % = 360 degree
float angle = convertToRadians(90);
angle -= convertToRadians(percent * 360 / 100);
float len = this.getWidth() > this.getHeight() ? this.getWidth() : this.getHeight();
float dy = (float) (Math.sin(angle) * len);
float dx = (float) (Math.cos(angle) * len);
Vector2 line = new Vector2(center.x + dx, center.y + dy);
Vector2 v = IntersectPoint(line);
if (intersectAt == IntersectAt.TOP) {
if (v.x >= this.getWidth() / 2) {
fv = new float[]{
center.x,
center.y,
centerTop.x,
centerTop.y,
leftTop.x,
leftTop.y,
leftBottom.x,
leftBottom.y,
rightBottom.x,
rightBottom.y,
rightTop.x,
rightTop.y,
v.x,
v.y
};
} else {
fv = new float[]{
center.x,
center.y,
centerTop.x,
centerTop.y,
v.x,
v.y
};
}
} else if (intersectAt == IntersectAt.BOTTOM) {
fv = new float[]{
center.x,
center.y,
centerTop.x,
centerTop.y,
leftTop.x,
leftTop.y,
leftBottom.x,
leftBottom.y,
v.x,
v.y
};
} else if (intersectAt == IntersectAt.LEFT) {
fv = new float[]{
center.x,
center.y,
centerTop.x,
centerTop.y,
leftTop.x,
leftTop.y,
v.x,
v.y
};
} else if (intersectAt == IntersectAt.RIGHT) {
fv = new float[]{
center.x,
center.y,
centerTop.x,
centerTop.y,
leftTop.x,
leftTop.y,
leftBottom.x,
leftBottom.y,
rightBottom.x,
rightBottom.y,
v.x,
v.y
};
} else // if (intersectAt == IntersectAt.NONE)
{
fv = null;
}
}
#Override
public void draw(Batch batch, float parentAlpha) {
if (fv == null) return;
batch.end();
drawMe();
batch.begin();
}
public void drawMe() {
EarClippingTriangulator e = new EarClippingTriangulator();
ShortArray sv = e.computeTriangles(fv);
PolygonRegion polyReg = new PolygonRegion(texture, fv, sv.toArray());
PolygonSprite poly = new PolygonSprite(polyReg);
poly.setSize(PROGRESS_WIDTH,PROGRESS_HEIGHT);
poly.setPosition(posX,posY);
poly.setOrigin(poly.getOriginX(), poly.getOriginY());
poly.setRotation(this.getRotation());
poly.setColor(Color.GREEN);
polyBatch.begin();
poly.draw(polyBatch);
polyBatch.end();
}
float convertToDegrees(float angleInRadians) {
float angleInDegrees = angleInRadians * 57.2957795f;
return angleInDegrees;
}
float convertToRadians(float angleInDegrees) {
float angleInRadians = angleInDegrees * 0.0174532925f;
return angleInRadians;
}
}
and my init function:
ProgressCircle sprite;
private void initCircleProgress() {
Group group = new Group();
Image downBackground = new Image(atlas.findRegion("progressBackground"));
downBackground.setColor(Color.BLUE);
downBackground.setSize(USER_SCREEN_SIZE_WIDTH/5,USER_SCREEN_SIZE_WIDTH/5);
downBackground.setPosition(10,USER_SCREEN_SIZE_HEIGHT-(2*downBackground.getHeight()+20));
sprite = new ProgressCircle(atlas.findRegion("progressBackground"), pbatch,
downBackground.getWidth(),downBackground.getHeight(),downBackground.getX(),downBackground.getY());
sprite.setSize(downBackground.getWidth(),downBackground.getHeight());
sprite.setSize(downBackground.getX(),downBackground.getY());
Image label = new Image(atlas.findRegion("progressBackground"));
label.setSize(downBackground.getWidth()*0.8f,downBackground.getHeight()*0.8f);
label.setPosition(downBackground.getX()+(downBackground.getWidth()-label.getWidth())/2,
downBackground.getY()+(downBackground.getHeight()-label.getHeight())/2);
label.setColor(Color.WHITE);
group.addActor(downBackground);
group.addActor(sprite);
group.addActor(label);
group.setPosition(10,GAME_SIZE_HEIGHT-(group.getHeight()+20));
stage.addActor(group);
}
You need a circular gradient to mask out the desired parts.
Incrementing the masking values over time will result in a circular motion.
As you can see in the link to masking there are several methods to achieve this. A stencil buffer would be a good choice but can result in jaggy edges. Writing your own shader would be perfect but kinda hard if you never wrote a shader. You can also try to parse both pix maps and decide what pixels to draw while looping through both pixmaps. If the masking image and your source have equal texture space you can do this in one loop so it would not be that much slower then a shader and whatever works for you is a good solution, you can always optimize later.

PHASER ALTARA Struggling with motion paths, enemy ai and animations

Basically I want to make my sprite follow a motion path and depending on its direction it is going, it will play a particular animation. i.e. moving up will display its back, moving left will display the left side of the sprite and so on.
I've tried for hours but to no avail in trying to make this work. I had some luck using prototype but the final game will be using the structure below. ANY help will be appreciated.
/*
* initalise Phaser framework with width:960px, height:540px
*/
var game = new Phaser.Game(960, 540, Phaser.AUTO, 'gameContainer', { preload: preload, create: create, update: update, });
/*
* Preload runs before the game starts. Assets such as images and sounds such be preloaded here.
* A webserver is required to load assets.
*
* Also in this function we set game scale so it full browser width.
*/
function preload() {
// set to scale to full browser width
this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
this.scale.parentIsWindow = true;
//set the background color so can confirm the game renders in the browser
this.stage.backgroundColor = '#4488cc';
this.game.renderer.renderSession.roundPixels = true;
//preload images & sounds
//game.load.image('key', 'folder/filename.png');
//this.load.image('nazi', 'image/nazi.png');
game.load.spritesheet('nazi', 'images/nazi.png', 128, 128, 6);
this.bmd = null;
this.alien = null;
this.mode = 0;
//Use this website to set enemy movements http://phaser.io/waveforms. Export save data from the console log.
this.points = {
"type":0,"closed":true,"x":[120,120,260,260,200,180,120],"y":[368,108,108,308,308,368,368]
};
this.pi = 0;
this.path = [];
}
/*
* Add game variables here
*/
var nazi;
/*
* Create runs once only when Phaser first loads
* create the game scene by adding objects to the stage
*/
function create() {
bmd = this.add.bitmapData(this.game.width, this.game.height);
bmd.addToWorld();
/*
For testing
this.alien = this.add.sprite(0, 0, 'alien');
this.alien.anchor.set(0.5);
*/
this.nazi = this.add.sprite(0, 0, 'nazi');
this.nazi.anchor.set(0.5);
var py = this.points.y;
/*Original Code
//define the animation
nazi.animations.add('walk');
//start the animation at 30fps
nazi.animations.play('walk', 3, true);
*/
//define the animation
this.nazi.animations.add('walkDown', [2, 3]);
//start the animation at 30fps
this.nazi.animations.play('walkDown', 3, true);
//define the animation
this.nazi.animations.add('walkLR', [4, 5]);
//start the animation at 30fps
this.nazi.animations.play('walkLR', 3, true);
//define the animation
this.nazi.animations.add('walkUp', [0, 1]);
//start the animation at 30fps
this.nazi.animations.play('walkUp', 3, true);
}
function plot() {
this.bmd.clear();
this.path = [];
/*ROTATION CODE*/
var ix = 0;
/**/
//Sets the speed of the sprite
var x = 0.5 / game.width;
//looping through plotting points from x and y array
for (var i = 0; i <= 1; i += x) {
var px = this.math.linearInterpolation(this.points.x, i);
var py = this.math.linearInterpolation(this.points.y, i);
/* ROTATION CODE to follow direction of path*/
var node = { x: px, y: py, angle: 0 };
if (ix > 0)
{
node.angle = this.math.angleBetweenPoints(this.path[ix - 1], node);
}
this.path.push(node);
ix++;
/**/
//this.path.push( { x: px, y: py });
this.bmd.rect(px, py, 1, 1, 'rgba(255, 255, 255, 1)');
}
for (var p = 0; p < this.points.x.length; p++) {
this.bmd.rect(this.points.x[p]-3, this.points.y[p]-3, 6, 6, 'rgba(255, 0, 0, 1)');
}
}
/*
* Update runs continuously. Its the game loop function.
* Add collision detections and control events here
*/
function update() {
plot();
// Reset the players velocity (movement)
//this.nazi = 'nazi';
/* For Testing
this.alien.x = this.path[this.pi].x;
this.alien.y = this.path[this.pi].y;
//ROTATION CODE:
this.alien.rotation = this.path[this.pi].angle;
*/
this.nazi.x = this.path[this.pi].x;
this.nazi.y = this.path[this.pi].y;
//this.nazi.rotation = this.path[this.pi].angle;
this.pi++;
if (this.pi >= this.path.length)
{
this.pi = 0;
}
/*
// Flipping the player image based on the velocity
if(nazi.body.velocity.x > 0){
//player is moving right
nazi.scale.x = -1;
nazi.animations.play('walkLR');
}
else if(nazi.body.velocity.x < 0){
//player is moving left
nazi.scale.x = 1; //flip the image
nazi.animations.play('walkLR');
}
else if (nazi.body.velocity.y < 0){
nazi.animations.play('walkUp');
}
else if(nazi.body.velocity.y > 0){
//player is not moving
nazi.animations.play('walkDown');
}
*/
}

Making falling objects come at random angles in AS3

I am making a missile defense type of game and am trying to get the missiles to fall at random angles. I also need the bullet image to turn at the angle I am shooting at. I am very unfamiliar with angles in AS3 so I need some help.
Code:
import spark.components.Image;
public var missiles:Array;
public var bullets:Array;
public var playerLife:Number;
public var targetX:Number;
public var targetY:Number;
public function init():void {
startGame();
}
public function onEnterFrame(e:Event):void {
if(Math.random() <.05 ){
//make a new missle
var newMissile:Image = new Image();
//draw to is
newMissile.source = "assets/missileDown.jpg";
//position it
newMissile.x = Math.random() * stage.stageWidth;
//animate it
newMissile.addEventListener(Event.ENTER_FRAME, onMissileEnterFrame);
//add it to missle array
missiles.push(newMissile);
//add it to the screen
gameGroup.addElement(newMissile);
}
}
public function startGame():void {
//makes new arrays
//gets rid of old arrays
missiles = new Array();
bullets = new Array();
//set player life
playerLife = 5;
//show player life
playerHealth.text = String(playerLife);
//add animation and mouse interation
this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.addEventListener(MouseEvent.CLICK, fireWeapon);
//set game over alpha
gameEnd.alpha = 0;
reset.alpha = 0;
//set game start alpha
playerHealth.alpha = 1;
healthLabel.alpha = 1;
}
//updates the missle
public function onMissileEnterFrame(e:Event):void {
//reference to target
var targetMissile:Image = Image(e.currentTarget);
//move missle down
targetMissile.y += 10;
//if missle has gone too far, remove it and player loses life
if(targetMissile.y > stage.stageHeight) {
playerLife --;
removeMissile(targetMissile);
//show player life
playerHealth.text = String(playerLife);
}
//if player is dead, game over
if(playerLife <= 0) {
gameOver();
}
}
//update bullet
public function onBulletEnterFrame(e:Event):void {
//get reference to bullet
var thisBullet:Bullet = Bullet(e.currentTarget);
//animate towards point..
//calculate difference between current position and desired position
var diffX:Number = thisBullet.targX - thisBullet.x;
var diffY:Number = thisBullet.targY - thisBullet.y;
//move 10% of difference closer
thisBullet.x += diffX * .1;
thisBullet.y += diffY * .1;
//chekc for overlap between bullet and missles
for(var i:Number = 0; i < missiles.length; i++) {
//if they do overlap, remove missle
if( thisBullet.hitTestObject(missiles[i]) ) {
removeMissile(missiles[i]);
removeBullet(thisBullet);
break;
}
}
//if we're 'close enough' to the target position, remove bullet
if(Math.abs(diffX) < 10 && Math.abs(diffY) < 10) {
removeBullet(thisBullet);
}
}
//gets rid of a missle
public function removeMissile(targetMissile:Image):void {
//removes the missle from the missiles array
for(var i:Number = missiles.length - 1; i >= 0; i--) {
if(missiles[i] == targetMissile) {
missiles.splice(i,1);
break;
}
}
//don't animate anymore
targetMissile.removeEventListener(Event.ENTER_FRAME, onMissileEnterFrame);
//remove from stage
gameGroup.removeElement(targetMissile);
}
//removes bullet from stage
public function removeBullet(targetBullet:Bullet):void {
//stop animation
targetBullet.removeEventListener(Event.ENTER_FRAME, onBulletEnterFrame);
//remove from stage
gameGroup.removeElement(targetBullet);
}
//shoot a bullet at the mouse position
public function fireWeapon(e:MouseEvent):void {
//make a new bullet
var newBullet:Bullet = new Bullet();
newBullet.addEventListener(Event.ENTER_FRAME, onBulletEnterFrame);
//position near the earth in the center
var halfStage:Number = stage.stageWidth / 2;
newBullet.x = halfStage;
newBullet.y = 500;
//set target
newBullet.targX = stage.mouseX;
newBullet.targY = stage.mouseY;
//add it to the stage
gameGroup.addElement(newBullet);
}
//you lose
public function gameOver():void {
//remove missles
for(var i:Number = 0; i < missiles.length; i++) {
removeMissile(missiles[i]);
}
//stop interaction
stage.removeEventListener(MouseEvent.CLICK, fireWeapon);
//stop animation
this.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
//set game start alpha
playerHealth.alpha = 0;
healthLabel.alpha = 0;
//set game end alpha
gameEnd.alpha = 1;
reset.alpha = 1;
}
]]>
</fx:Script>
onEnterFrame
...
//position it
newMissile.x = Math.random() * stage.stageWidth;
//rotate it
newMissile.rotation = - (Math.random() * 60 - 30);
onMissileEnterFrame
...
//move missle down
//targetMissile.y += 10;
targetMissile.x -= 10 * Math.sin(targetMissile.rotation * Math.PI/180);
targetMissile.y += 10 * Math.cos(targetMissile.rotation * Math.PI/180);
fireWeapon
...
//set target
newBullet.targX = stage.mouseX;
newBullet.targY = stage.mouseY;
newBullet.rotation = - Math.atan((newBullet.x - newBullet.targX) / (newBullet.y - newBullet.targY)) * 180/Math.PI;

How can I rotate picture dynamically?

I have a resource in my prog (*.bmp image). When I start a timer, my image should rotate until I click "pause". I need a sample which explain me how I could to do this.
Currently I use this code:
void rotatewaiticon()
{
Graphics::TBitmap *bmpOriginal = new Graphics::TBitmap();
//bmpOriginal->LoadFromResourceName(0,"bmpcrug");
bmpOriginal->LoadFromFile("degrees.bmp");
FormMain->Image65->Picture->Assign(bmpOriginal);
Graphics::TBitmap *bmpCopy = new Graphics::TBitmap();
bmpCopy->Width = bmpOriginal->Height;
bmpCopy->Height = bmpOriginal->Width;
int wOr = bmpOriginal->Width, hOr = bmpOriginal->Height;
for(int x = 0; x < wOr; x++)
{
for(int y = 0; y < hOr; y++)
{
bmpCopy->Canvas->Pixels[hOr - y][x] = bmpOriginal->Canvas->Pixels[x][y];
}
}
/**/FormMain->Image65->Picture->Assign(bmpCopy);
bmpCopy->SaveToFile("degrees.bmp");
delete bmpOriginal, bmpCopy;
}
But I don't see a way to work with this file without saving it on a disk.

Resources