So i was trying to make a simple mobile game for a school project. I setted up a simple SurfaceView thing and builded it on my phone with Android 12 (Api 32), but it doesn't draw anything. It enters the draw function of the view, but i can't see an output. It only works on a old friend's tablet with Android 4.4.2.
MySurfaceView.java
package com.example.lyceumgame;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {
Bitmap image;
Paint paint;
float iX, iY, tX = 0, tY = 0;
float dx = 0, dy = 0;
Resources res;
MyThread myThread;
float ws, hs;
float iw, ih;
boolean isFirstDraw = true;
public MySurfaceView(Context context) {
super(context);
getHolder().addCallback(this);
res = getResources();
iX = 100;
iY = 100;
paint = new Paint();
paint.setColor(Color.YELLOW);
paint.setStrokeWidth(5);
setAlpha(0);
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
myThread = new MyThread(surfaceHolder, this);
myThread.setRunning(true);
myThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
boolean retry = true;
myThread.setRunning(false);
while (retry) {
try {
myThread.join();
retry = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
setAlpha(0);
if (isFirstDraw){
ws = canvas.getWidth();
hs = canvas.getHeight();
isFirstDraw = false;
}
canvas.drawRGB(0,255,0);
canvas.drawLine(iX, iY, tX, tY, paint);
if(tX != 0)
delta();
iX += dx;
iY += dy;
checkScreen();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
tX = event.getX();
tY = event.getY();
delta();
return true;
}
void delta(){
double ro = Math.sqrt(Math.pow(tX-iX, 2)+Math.pow(tY-iY, 2));
double k = 10;
dx = (float) (k * (tX - iX)/ro);
dy = (float) (k * (tY - iY)/ro);
}
private void checkScreen(){
if(iY + ih >= hs && iY <= 0)
dy = -dy;
if(iX + iw >= ws && iX <= 0)
dx = -dx;
}
}
MyThread.java
package com.example.lyceumgame;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
public class MyThread extends Thread {
boolean isRunning = false;
SurfaceHolder surfaceHolder;
MySurfaceView mySurfaceView;
long prevTime, nowTime;
int FPS=60;
int c=1000;
int koeff=c/FPS;
public MyThread(SurfaceHolder holder, MySurfaceView surfaceView) {
surfaceHolder = holder;
mySurfaceView = surfaceView;
prevTime = System.currentTimeMillis();
}
#Override
public void run() {
Canvas canvas;
while (isRunning){
if(!surfaceHolder.getSurface().isValid())
continue;
canvas = null;
nowTime = System.currentTimeMillis();
long ellapsedTime = nowTime - prevTime;
if(ellapsedTime > koeff){
prevTime = nowTime;
canvas = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder){
mySurfaceView.draw(canvas);
}
if (canvas != null){
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
void setRunning(boolean f){
isRunning = f;
}
}
MainActivity.java
package com.example.lyceumgame;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MySurfaceView(this));
}
}
My SDK was in different location and code like this worked fine. I tried invalidating caches and moving SDK to previous location. It didn't work.
Related
I am new to Android Studio and do not understand why the onSensorChanged() method does not give errors and warnings, but returns zero. I want to "roll the ball on the screen of the device." The graphic component works well. I see a ball with a constant speed of movement, and I want to adjust the speed by multiplying it by the angle of the screen and therefore my speed becomes - zero.
Please help me fix it.
I'm testing the application on a real device Xiaomi MI9 SE.
//MAIN ACTIVITY
package com.example.app_2;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class Gravity extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_gravity);
setContentView(new MovementView(this));
}
}
//PHYSICS
package com.example.app_2;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MovementView extends SurfaceView implements SurfaceHolder.Callback {
public float xPos;
public float yPos;
public float xVel;
public float yVel;
public float width;
public float height;
private float circleRadius;
private Paint circlePaint;
UpdateThread updateThread;
public MovementView(Context context) {
super(context);
getHolder().addCallback(this);
circleRadius = 30;
circlePaint = new Paint();
circlePaint.setColor(Color.RED);
xVel = 2 ; // скорость движения
yVel = 2 ; // шарика
}
#Override
public void onDraw(Canvas c) {
c.drawColor(Color.WHITE);
c.drawCircle(xPos, yPos, circleRadius, circlePaint);
}
public void updatePhysics() {
float xz, zy;
xz = Acceleration.Accel(1);
zy = Acceleration.Accel(-1);
xPos += xVel - xz;
yPos += yVel - zy;
if (yPos - circleRadius < 0 || yPos + circleRadius > height) {
//В случае ударов о верх или низ холста
if (yPos - circleRadius < 0) {
//Удар о верхнюю грань
yPos = circleRadius;
}else{
//Удар о нижнюю грань
yPos = height - circleRadius;
}
//Меняем направление шарика
yVel *= -1;
}
if (xPos - circleRadius < 0 || xPos + circleRadius > width) {
//В случае столкновений с правой или левой стенками
if (xPos - circleRadius < 0) {
//В случае столкновений с левой стенкой
xPos = circleRadius;
} else {
//В случае столкновений с правой стенкой
xPos = width - circleRadius;
}
//Меняем x направление на обратное
xVel *= -1;
}
}
public void surfaceCreated(SurfaceHolder holder) {
Rect surfaceFrame = holder.getSurfaceFrame();
width = surfaceFrame.width();
height = surfaceFrame.height();
xPos = width / 2;
yPos = height / 2;
updateThread = new UpdateThread(this);
updateThread.setRunning(true);
updateThread.start();
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
updateThread.setRunning(false);
while (retry) {
try {
updateThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
}
//THREAD
package com.example.app_2;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
public class UpdateThread extends Thread{
private long time;
private final int fps = 5;
private boolean toRun = false;
private MovementView movementView;
private SurfaceHolder surfaceHolder;
UpdateThread(MovementView rMovementView) {
movementView = rMovementView;
surfaceHolder = movementView.getHolder();
}
void setRunning(boolean run) {
toRun = run;
}
#Override
public void run() {
Canvas c;
while (toRun) {
long cTime = System.currentTimeMillis();
//if ((cTime - time) <= (100000 / fps)) {
c = null;
try {
c = surfaceHolder.lockCanvas(null);
movementView.updatePhysics();
movementView.onDraw(c);
} finally {
if (c != null) {
surfaceHolder.unlockCanvasAndPost(c);
}
}
//}
time = cTime;
}
}
}
//ACCELERATION
package com.example.app_2;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.IBinder;
import androidx.core.content.ContextCompat;
import static android.content.Context.SENSOR_SERVICE;
import static android.hardware.Sensor.TYPE_ROTATION_VECTOR;
import static androidx.core.content.ContextCompat.getSystemService;
public class Acceleration extends Service implements SensorEventListener {
public SensorManager sensorManager;
public static float xy_angle, xz_angle, zy_angle;
public Acceleration(Context pContext) {
sensorManager = (SensorManager) pContext.getSystemService(SENSOR_SERVICE);
assert sensorManager != null;
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(TYPE_ROTATION_VECTOR),
SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
assert sensorManager != null;
xy_angle = sensorEvent.values[0];
xz_angle = sensorEvent.values[1];
zy_angle = sensorEvent.values[2];
}
public static float Accel(int a){
float angle;
if (a > 0){
angle = xz_angle;
} else {
angle = zy_angle;
}
return angle;
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
I expect Acceleration.Accel(1) to return the value of the TYPE_ROTATION_VECTOR sensor at the time of the data request, but I always get zero.
What you need to do is pass your application's Context to your Acceleration class so that your SensorManager can get initialized. The way you had the SensorManager getting initialized inside the onSensorChanged() method meant that the SensorManager was never even getting setup because onSensorChanged() was never even getting called.
So in the revised Acceleration class below, I added a constructor which you will then need to call with your application's Context passed in as an argument:
public class Acceleration extends Service implements SensorEventListener {
public SensorManager sensorManager;
public static float xy_angle, xz_angle, zy_angle;
public Acceleration(Context pContext) {
sensorManager = (SensorManager) pContext.getSystemService(SENSOR_SERVICE);
assert sensorManager != null;
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(TYPE_ROTATION_VECTOR),
SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
xy_angle = sensorEvent.values[0];
xz_angle = sensorEvent.values[1];
zy_angle = sensorEvent.values[2];
}
public static float accel(int a) {
float angle;
if (a > 0) {
angle = xz_angle;
} else {
angle = zy_angle;
}
return angle;
}
}
In your Gravity class, just initialize an Acceleration object:
public class Gravity extends AppCompatActivity {
Acceleration acceleration;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MovementView(this));
acceleration = new Acceleration(this);
}
}
I have a sprite sheet of 612x864 dimension with 5 rows and 5 columns .My problem is how can I load it and animate it? I want to move the cat sprite in y-axis only .I've already try but my code is not working properly. Here is my code.
In GameView.java
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GameView extends SurfaceView {
private Bitmap bmp;
private SurfaceHolder holder;
private GameLoopThread gameLoopThread;
private Sprite sprite;
public GameView(Context context) {
super(context);
gameLoopThread = new GameLoopThread(this);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
gameLoopThread.setRunning(false);
while (retry) {
try {
gameLoopThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.catsprite);
sprite = new Sprite(this,bmp);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
sprite.onDraw(canvas);
}
}
GameLoopThread.java
import android.graphics.Canvas;
public class GameLoopThread extends Thread {
static final long FPS = 10;
private GameView view;
private boolean running = false;
public GameLoopThread(GameView view) {
this.view = view;
}
public void setRunning(boolean run) {
running = run;
}
#Override
public void run() {
long ticksPS = 1000 / FPS;
long startTime;
long sleepTime;
while (running) {
Canvas c = null;
startTime = System.currentTimeMillis();
try {
c = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
view.onDraw(c);
}
} finally {
if (c != null) {
view.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime = ticksPS-(System.currentTimeMillis() - startTime);
try {
if (sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
} catch (Exception e) {}
}
}
}
Sprite.java
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
public class Sprite {
private static final int BMP_ROWS = 5;
private static final int BMP_COLUMNS = 5;
private int x = 0;
private int y = 0;
private int ySpeed = 3;
private GameView gameView;
private Bitmap bmp;
private int currentFrame = 1;
private int width;
private int height;
public Sprite(GameView gameView, Bitmap bmp) {
this.gameView = gameView;
this.bmp = bmp;
this.width = bmp.getWidth() / BMP_COLUMNS;
this.height = bmp.getHeight() / BMP_ROWS;
}
private void update() {
if (y > gameView.getWidth() - width - y) {
ySpeed = -5;
}
if (y + y < 0) {
ySpeed = 5;
}
y = y + ySpeed;
currentFrame = ++currentFrame % BMP_COLUMNS;
}
public void onDraw(Canvas canvas) {
update();
int srcX = currentFrame * width;
int srcY = 1 * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
}
I'll recommend you to use this library. It's great for Sprite Animation. It has some limitations though, but it works fine.
Here is the code how I done it.
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.runningcat);
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int frameWidth = width / 5; //you have 5 columns
int frameHeight = height / 5; //and 5 rows
int frameNum = 25; //there would be 25 images
SpriteSheetDrawer spriteSheetDrawer = new SpriteSheetDrawer(
bitmap,
frameWidth,
frameHeight,
frameNum)
.spriteLoop(true)
.frequency(2); //change it as per your need
DisplayObject displayObject = new DisplayObject();
displayObject
.with(spriteSheetDrawer)
.tween()
.tweenLoop(true)
.transform(0, 0) //I have changed it according to my need, you can also do this by changing these values
.toX(4000, 0) //this one too.
.end();
//In actual example, it's set as animation starts from one end of the screen and goes till the other one.
FPSTextureView textureView = (FPSTextureView) findViewById(R.id.fpsAnimation);
textureView.addChild(displayObject).tickStart();
Problem is in src value that you're using in method. canvas.drawBitmap(bmp, src, dst, null); srcY should be zero. I've tested here.
private Bitmap character;
private counter,charFrame;
private RectF annonymousRectF;
private Rect annonymousRect;
public Sprite() {
character=BitmapFactory.decodeResource(context.getResources(), R.drawable.flipchar2);
annonymousRect=new Rect();
annonymousRectF=new RectF();
}
public void update() {
counter++;
if(counter%5==0)
if(charFrame<NO_CHAR_FRAME-1)
charFrame++;
else
charFrame=0;
}
public void draw(){
annonymousRect.set(charFrame*character.getWidth()/NO_CHAR_FRAME,0,(charFrame+1)*character.getWidth()/NO_CHAR_FRAME,character.getHeight());
annonymousRectF.set(-width*.015f,height*.35f,width*.5f,height*.58f); //set value according to where you want to draw
canvas.drawBitmap(character, annonymousRect,annonymousRectF, null);
}
so i was following retro-chickens tutorial online on how to make a 2d game on android studio and i have run across a problem and i tried to figure it out but i just cant seemm to find a solution. The problem occured on his 2nd video (https://www.youtube.com/watch?v=Rliwg0sELJo) where he runs his code and rectangle appears on the screen which he can move around. For me the rectangle doesnt appear on the canvas for some reason, it is just a blank canvas even though i have the exact same code as him (i have gone back and checked).
At times my application sometimes doesnt even launch and gives me error like this (I have the latest sdk version and everything):
Cold swapped changes.
$ adb shell am start -n "com.example.ridhavraj.stardrifter/com.example.ridhavraj.stardrifter.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Connected to process 3319 on device emulator-5554
W/System: ClassLoader referenced unknown path: /data/app/com.example.ridhavraj.stardrifter-2/lib/x86
I/InstantRun: Instant Run Runtime started. Android package is com.example.ridhavraj.stardrifter, real application class is null.
W/System: ClassLoader referenced unknown path: /data/app/com.example.ridhavraj.stardrifter-2/lib/x86
I/OpenGLRenderer: Initialized EGL, version 1.4
D/OpenGLRenderer: Swap behavior 1
[ 11-11 20:20:52.858 3319: 3343 D/ ]
HostConnection::get() New Host Connection established 0xaee13300, tid 3343
A/libc: Fatal signal 6 (SIGABRT), code -6 in tid 3343 (Thread-5)
[ 11-11 20:20:53.138 1214: 1214 W/ ]
debuggerd: handling request: pid=3319 uid=10072 gid=10072 tid=3343
Application terminated.
Here is the code that i have made from the video:
[GameObject Interface]
package com.example.ridhavraj.stardrifter;
import android.graphics.Canvas;
public interface GameObject {
public void draw(Canvas canvas);
public void update();
}
[MainActivity Class]
package com.example.ridhavraj.stardrifter;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
//setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new GamePanel(this));
}
}
[MainThread Class]
package com.example.ridhavraj.stardrifter;
import android.graphics.Canvas;
import android.provider.Settings;
import android.view.SurfaceHolder;
public class MainThread extends Thread{
public static final int MAX_FPS = 30;
private double averageFPS;
private SurfaceHolder surfaceHolder;
private GamePanel gamePanel;
private boolean running;
public static Canvas canvas;
public void setRunning(boolean running)
{
this.running = running;
}
public MainThread(SurfaceHolder surfaceHolder, GamePanel gamePanel)
{
super();
this.surfaceHolder = surfaceHolder;
this.gamePanel = gamePanel;
}
#Override
public void run()
{
long startTime;
long timeMillis = 1000/MAX_FPS;
long waitTime;
int frameCount = 0;
long totalTime = 0;
long targetTime = 1000/MAX_FPS;
while(running)
{
startTime = System.nanoTime();
canvas = null;
try
{
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder)
{
this.gamePanel.update();
this.gamePanel.draw(canvas);
}
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if (canvas != null)
{
try
{
surfaceHolder.unlockCanvasAndPost(canvas);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
timeMillis = (System.nanoTime()-startTime)/1000000;
waitTime = targetTime - timeMillis;
try
{
if (waitTime > 0)
{
this.sleep(waitTime);
}
}
catch (Exception e)
{
e.printStackTrace();
}
totalTime += System.nanoTime() - startTime;
frameCount++;
if (frameCount == MAX_FPS)
{
averageFPS = 1000/((totalTime/frameCount)/1000000);
frameCount = 0;
totalTime = 0;
System.out.println(averageFPS);
}
}
}
}
[GamePanel Class]
package com.example.ridhavraj.stardrifter;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GamePanel extends SurfaceView implements SurfaceHolder.Callback {
private MainThread thread;
private Player player;
private Point playerPoint;
public GamePanel(Context context)
{
super(context);
getHolder().addCallback(this);
thread = new MainThread(getHolder(), this);
player = new Player(new Rect(100,100,200,200), Color.rgb(255,0,0));
playerPoint = new Point(150,150);
setFocusable(true);
}
#Override
public void surfaceChanged(SurfaceHolder Holder, int format, int width, int height)
{
}
#Override
public void surfaceCreated(SurfaceHolder holder)
{
thread = new MainThread(getHolder(), this);
thread.setRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder)
{
boolean retry = true;
while(true)
{
try
{
thread.setRunning(false);
thread.join();
}
catch (Exception e)
{
e.printStackTrace();
}
retry = false;
}
}
public boolean onTouchEvent(MotionEvent event)
{
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
playerPoint.set((int)event.getX(), (int)event.getY());
}
return true;
//return super.onTouchEvent(event);
}
public void update()
{
player.update(playerPoint);
}
#Override
public void draw(Canvas canvas)
{
super.draw(canvas);
canvas.drawColor(Color.WHITE);
player.draw(canvas);
}
}
[Player Class]
package com.example.ridhavraj.stardrifter;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Canvas;
import android.graphics.Rect;
public class Player implements GameObject{
private Rect rectangle;
private int color;
public Player(Rect rectangle, int Color)
{
this.rectangle = rectangle;
this.color = color;
}
#Override
public void draw(Canvas canvas)
{
Paint paint = new Paint();
paint.setColor(color);
canvas.drawRect(rectangle, paint);
}
#Override
public void update()
{
}
public void update(Point point)
{
//l,t,r,b
rectangle.set(point.x-rectangle.width()/2, point.y-rectangle.height()/2, point.x+rectangle.width()/2, point.y+rectangle.height()/2);
}
}
I dont clue what i am doing wrong, any help would be greatly appreciated.
Well Turns out guys, i am retarded, there was a typo in the player class
private Rect rectangle;
private int color;
public Player(Rect rectangle, int Color [THIS SHOULD BE 'color' and not 'Color')
{
this.rectangle = rectangle;
this.color = color;
}
for 3D Rectangle(cube) copy whole code to your CustomView Class
Paste This into onDraw() method
drawCube(
fp.mX.toInt(), fp.mY.toInt(),
100 + (fp.mCx.toInt() - fp.mX.toInt()),
100 + fp.mCy.toInt() - fp.mY.toInt(),
mPaint, mCanvas!!
)
drawCube(
fp.mX.toInt(), fp.mY.toInt(),
100 + (fp.mCx.toInt() - fp.mX.toInt()),
100 + fp.mCy.toInt() - fp.mY.toInt(),
mStrokePaint, mCanvas!!
)
3D Cube Function Code
private fun drawCube(
x: Int,
y: Int,
width: Int,
height: Int,
paint: Paint,
canvas: Canvas
) {
val p1 = Point(x, y)
val p2 = Point(x, y + height)
val p3 = Point(x + width, y + height)
val p4 = Point(x + width, y)
val p5 = Point(x + width / 2, y - height / 2)
val p6 = Point(x + 3 * width / 2, y - height / 2)
val p7 = Point(x + 3 * width / 2, y + height / 2)
val path = Path()
path.fillType = Path.FillType.EVEN_ODD
path.moveTo(p1.x.toFloat(), p1.y.toFloat())
path.lineTo(p2.x.toFloat(), p2.y.toFloat())
path.lineTo(p3.x.toFloat(), p3.y.toFloat())
path.lineTo(p4.x.toFloat(), p4.y.toFloat())
path.lineTo(p1.x.toFloat(), p1.y.toFloat())
path.lineTo(p5.x.toFloat(), p5.y.toFloat())
path.lineTo(p6.x.toFloat(), p6.y.toFloat())
path.lineTo(p4.x.toFloat(), p4.y.toFloat())
path.moveTo(p3.x.toFloat(), p3.y.toFloat())
path.lineTo(p7.x.toFloat(), p7.y.toFloat())
path.lineTo(p6.x.toFloat(), p6.y.toFloat())
path.lineTo(p4.x.toFloat(), p4.y.toFloat())
path.close()
canvas.drawPath(path, paint)
}
i want to execute this code in the following code again and again in defined intervals
for (Sprite sprite : sprites) {
sprite.onDraw(canvas);
}
i tryed few methods but i am stuck with errors . because i have all my animation timed with sleep and thread extended class
package com.okok;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.SurfaceHolder.Callback;
public class GameView extends SurfaceView {
private Bitmap bmp;
private SurfaceHolder holder;
private GameLoopThread gameLoopThread;
private List<Sprite> sprites = new ArrayList<Sprite>();
private long lastClick;
private Bitmap bmpBlood;
private List<TempSprite> temps = new ArrayList<TempSprite>();
private int mint;
public GameView(Context context) {
super(context);
gameLoopThread = new GameLoopThread(this);
holder = getHolder();
holder.addCallback(new Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
createSprites();
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
bmpBlood = BitmapFactory.decodeResource(getResources(), R.drawable.blast);
}
private void createSprites() {
sprites.add(createSprite(R.drawable.greenenact));
sprites.add(createSprite(R.drawable.greenenact));
sprites.add(createSprite(R.drawable.greenenact));
}
private Sprite createSprite(int resouce) {
Bitmap bmp = BitmapFactory.decodeResource(getResources(), resouce);
return new Sprite(this, bmp);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.rgb(21, 181, 195));
for (int i = temps.size() - 1; i >= 0; i--) {
temps.get(i).onDraw(canvas);
}
for (Sprite sprite : sprites) {
sprite.onDraw(canvas);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (System.currentTimeMillis() - lastClick > 500) {
lastClick = System.currentTimeMillis();
synchronized (getHolder()) {
float x = event.getX();
float y =event.getY();
for (int i = sprites.size() - 1; i >= 0; i--) {
Sprite sprite = sprites.get(i);
if (sprite.isCollition(x, y)) {
sprites.remove(sprite);
temps.add(new TempSprite(temps, this, x, y, bmpBlood));
break;
}
}
}
}
return true;
}
}
This is the GameLoopThread class i used to move things
package com.okok;
import android.graphics.Canvas;
public class GameLoopThread extends Thread {
static final long FPS = 10;
private GameView view;
private boolean running = false;
public GameLoopThread(GameView view) {
this.view = view;
}
public void setRunning(boolean run) {
running = run;
}
#Override
public void run() {
long ticksPS = 1000 / FPS;
long startTime;
long sleepTime;
while (running) {
Canvas c = null;
startTime = System.currentTimeMillis();
try {
c = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
view.onDraw(c);
}
} finally {
if (c != null) {
view.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime = ticksPS - (System.currentTimeMillis() - startTime);
try {
if (sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
} catch (Exception e) {}
}
}
}
Try something like:
private void createSprites() {
{
new Thread(new Runnable() {
public void run() {
for (int z =0; z<20; z++ ) // total of 20 sprites
try
{
Thread.sleep(5000); // new enemy every 5 seconds
sprites.add(createSprite(R.drawable.image));
z++;
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}).start();
}
why does this not work? it prints the locations as the should but it does not move the image on the screen? i am using an emulator.
i think the image should be moving around but it stays in the same place even though the x and y values are changing. i think the problem may be the canvas i am using when i call onDraw(canvas). what can i do to this canvas to make it work (if the canvas is the problem)?
if this is not enough detail please tell me. code below;
GameView.java
package com.example.game;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.View;
public class GameView extends View implements Runnable{
Thread gameLoop = new Thread(this);
boolean running = false;
int x = 10;
int y = 10;
Canvas canvas = new Canvas();
private Bitmap bmp;
public GameView(Context context) {
super(context);
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
}
#Override
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(bmp, x, y, null);
System.out.println(x);
if(x < 100) {
x+=10;
}
if(x >= 99 && y < 400) {
y+=10;
}
if(y > 350 && x >= 99) {
x = 10;
y = 10;
}
}
public void start() {
if(!running) {
running = true;
gameLoop.start();
}
}
public void stop() {
if(running) {
running = false;
}
}
#Override
public void run() {
while(running) {
try{
onDraw(canvas);
Thread.sleep(1000);
}catch(Exception exc) {System.err.println("error sleep interup");}
}
}
}
Main.java
package com.example.game;
import android.app.Activity;
import android.os.Bundle;
public class Main extends Activity {
GameView gv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gv = new GameView(this);
setContentView(gv);
gv.start();
}
}
You should put the object back on the canvas after you calculated the x and y coordinates.
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
System.out.println(x);
if(x < 100) {
x+=10;
}
if(x >= 99 && y < 400) {
y+=10;
}
if(y > 350 && x >= 99) {
x = 10;
y = 10;
}
canvas.drawBitmap(bmp, x, y, null);
}