Ok, so I've been working on a little game, and there's a problem in the rendering code. So, I tried to follow a tutorial for working with the SurfaceView, and so this is what I have so far:
GameSurface.java
package com.spng453.afirelitroom;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GameSurface extends SurfaceView implements SurfaceHolder.Callback {
private GameThread thread;
public SurfaceHolder surfaceHolder;
DisplayMetrics metrics = GameActivity.metrics;
final private int sX = metrics.widthPixels;
final private int sY = metrics.heightPixels;
private Paint mainBTheme = new Paint();
Rect fireButton = new Rect(0, sY/2+50, sX, sY/2-50);
public GameSurface(Context context) {
super(context);
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
this.setWillNotDraw(false);
thread = new GameThread(surfaceHolder, this);
this.setFocusable(true);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
thread.setRunning(true);
thread.run();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean done = false;
while(!done) {
try {
thread.join();
done = true;
}
catch (InterruptedException e) {
}
}
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawRGB(255, 255, 0);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
return true;
}
}
and the code in
GameThread.java:
package com.spng453.afirelitroom;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.SurfaceHolder;
public class GameThread extends Thread {
DisplayMetrics metrics = GameActivity.metrics;
final private int sX = metrics.widthPixels;
final private int sY = metrics.heightPixels;
private int FPS = 30;
private boolean running;
public SurfaceHolder surfaceHolder;
public GameSurface gameSurface;
public Canvas canvas;
private long firstTime = 0L, secondTime = 0L; //fps stuff
private Paint mainBTheme = new Paint();
//fire page
Rect fireButton = new Rect(0, sY/2+50, sX, sY/2-50);
Rect leftButton = new Rect();
Rect rightButton = new Rect();
//city/resources page
public void setRunning(boolean running) {
this.running = running;
}
public GameThread(SurfaceHolder surfaceHolder, GameSurface gameSurface) {
super();
this.surfaceHolder = surfaceHolder;
this.gameSurface = gameSurface;
mainBTheme.setColor(Color.BLACK);
}
#Override
public void run() {
while (running) {
//hey i guess i have to cap fps :(
firstTime = System.nanoTime();
//do the game here
canvas = null;
canvas = surfaceHolder.lockCanvas();
gameSurface.onDraw(canvas);
surfaceHolder.unlockCanvasAndPost(canvas);
secondTime = System.nanoTime();
if (secondTime/1000000 - firstTime/1000000 < 1000/FPS) { //the if the lag is less than the distance between frames at 30 fps
try {
Thread.sleep(1000/FPS - (secondTime/1000000 - firstTime/1000000));
} catch (InterruptedException e) {
}
}
}
}
}
So, my problem is that when I try to call onDraw in the GameThread here:
canvas = null;
canvas = surfaceHolder.lockCanvas();
gameSurface.onDraw(canvas);
surfaceHolder.unlockCanvasAndPost(canvas);
it does absolutely nothing. It doesn't draw whatever I put in onDraw, though if I put a Log call in the onDraw I know it executes. It doesn't produce an error message, either. Thanks for help in advanced!
Try this:
Change your method:
#Override
protected void onDraw(Canvas canvas) {
canvas.drawRGB(255, 255, 0);
}
By this:
#Override
protected void onDraw(Canvas canvas) {
canvas.drawRGB(255, 255, 0);
super.onDraw(canvas);
}
Also, try change this lines:
//do the game here
canvas = null;
canvas = surfaceHolder.lockCanvas();
gameSurface.onDraw(canvas);
surfaceHolder.unlockCanvasAndPost(canvas);
By this ones:
Canvas canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
gameSurface.onDraw(canvas);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (canvas != null)
surfaceHolder.unlockCanvasAndPost(canvas);
}
Also keep note that the while loop it's running really fast no giving chance to draw the canvas. The thread sleep isn't working very well. Look at this resources, there is explained how do the game loop properly. And if you wanna test it right now, just erase the while.
Android game loop explained
Android game basic structure
Hope this helps :]
Okay, so it turns out that it was a problem with the FPS code executing too fast. I solved it by doing this:
#Override
public void run() {
// TODO Auto-generated method stub
final int fps = 30;
Timer fpsTimer = new Timer();
fpsTimer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
Canvas canvas;
canvas = null;
try {
canvas = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
onDraw(canvas);
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}, 0, 1000/fps);
}
Related
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 am currently designing a basic sprite class for java for android because for I don't wish to use a 2d engine and Google doesn't provide any sprite APIs for some reason...
Anyways, my question is in regards to my Classes I have designed. I have a Sprite Class that takes a bitmap and turns it into a "sprite". This sprite can then be passed to a custom view I have created when the user creates a new "SpriteContainer"
My code for the DynamicSpriteContainer is as follows:
package com.me.spriteGraphics;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class DynamicSpriteContainer extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder holder;
public int x, y;
private Bitmap b;
public Sprite sprite;
private Canvas c = new Canvas();
private boolean bool = false;
public DynamicSpriteContainer(Context context, Sprite spriteImage) {
//public ImageView(Context context) {
super(context);
//get sprite
b = spriteImage.getBitmap();
//set holder
holder = getHolder();
holder.addCallback(this);
//set position
x = y = 0;
update();
}
public void surfaceCreated(SurfaceHolder holder) {
c = holder.lockCanvas();
c.drawARGB(255, 150, 150, 10);
//set up bitmap image
c.drawBitmap(b, x, y, null);
holder.unlockCanvasAndPost(c);
update();
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
public void surfaceDestroyed(SurfaceHolder holder) {
}
private void update() {
//this code will alter the character in the way the developer specifies (per frame)
Thread repeat = new Thread( new Runnable() {
public void run() {
try {
//move sprite in constant motion
while (bool) {
//redraw
c = holder.lockCanvas();
c.drawARGB(255, 150, 150, 10);
//set up bitmap image
c.drawBitmap(b, x, y, null);
holder.unlockCanvasAndPost(c);
}
} catch (Error e) {
e.printStackTrace();
bool = false;
}
}
});
repeat.start();
}
public void setX(int x) {
//notice how this same code above has the holder, the holder is recognized above, not here.
c = holder.lockCanvas();
c.drawARGB(255, 150, 150, 10);
//set up bitmap image
c.drawBitmap(b, x, y, null);
holder.unlockCanvasAndPost(c);
}
//set the info on pause, resume, stop...
//this data is for error stopping, so the app can resume and stop without passing an error to the user!
public void passInfo(boolean isPaused, boolean isResumed, boolean isStopped) {
if (isPaused && sprite.auto) {
bool = false;
}
if (isResumed && sprite.auto) {
bool = true;
}
if (isStopped && sprite.auto) {
bool = false;
}
}
}
Sorry for the long code excerpt.
The main issue is that inside the update() function, the holder is recognized, but inside the setX(), it's not...
How can I have the setX() recognize the holder?
Thank you soo much in advance!!!
I am making a game which requires the sprites to move towards the bottom of the screen. You can imagine it a bit like a rhythm game(guitar hero). However, I am having problems as the sprites are not moving at all even if the loop seems to work fine.
The GamePanel-
package com.jollygent.tapthepointer;
import java.util.ArrayList;
import java.util.Random;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GamePanel extends SurfaceView{
SurfaceHolder holder;
GameLoopThread loop;
GamePanel game = this;
Random rand;
int y;
//ArrayList<Pointers> pointers = new ArrayList<Pointers>();
Pointers pointers;
public GamePanel(Context context) {
super(context);
holder = getHolder();
loop = new GameLoopThread(this);
rand = new Random();
pointers = new Pointers(rand.nextInt(4)+1,getWidth()/2,0,this);
//placeholder
this.setBackgroundColor(Color.WHITE);
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
loop.setRunning(false);
}
#Override
public void surfaceCreated(SurfaceHolder arg0) {
loop = new GameLoopThread(game);
if(!loop.isRunning()){
loop.setRunning(true);
loop.start();
}
else{
loop.setPause(false);
}
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stubn
}
});
}
public GameLoopThread getLoop(){
return loop;
}
public void update(){
}
public void draw(Canvas canvas){
pointers.draw(canvas);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStrokeWidth(20);
paint.setStyle(Paint.Style.STROKE);
canvas.drawLine(0,getHeight()/2 + 50,getWidth(),getHeight()/2 + 50, paint);
}
}
The Pointer class
package com.jollygent.tapthepointer;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
public class Pointers {
GamePanel game;
private int x,y;
Bitmap pointer;
Bitmap rotated_pointer;
Matrix matrix;
public Pointers(int type,int x,int y,GamePanel game){
this.game = game;
this.x = x;
this.y = y;
pointer = BitmapFactory.decodeResource(game.getResources(),R.drawable.pointer_xx);
matrix = new Matrix();
switch(type){
//points right
case 1:
matrix.postRotate(90);
break;
//points left
case 2:
matrix.postRotate(-90);
break;
//points up
case 3:
rotated_pointer = pointer;
break;
//points down
case 4:
matrix.postRotate(180);
break;
}
rotated_pointer = Bitmap.createBitmap(pointer,0,0,pointer.getHeight(),pointer.getWidth(), matrix,true);
}
public void update(){
/*if(y < game.getHeight()){
y += pointer.getHeight();
}*/
}
public int getHeight(){
return pointer.getHeight();
}
public void draw(Canvas canvas){
y++;//placeholder movement to see if the sprite actually moves. It doesn't.
canvas.drawBitmap(rotated_pointer,x,y,null);
}
}
Finally, I think it's necessary to post the GameLoopThread-
package com.jollygent.tapthepointer;
import android.graphics.Canvas;
public class GameLoopThread extends Thread{
GamePanel game;
boolean running = false;
boolean paused = false;
Canvas canvas;
static final int FPS = 10;
public GameLoopThread(GamePanel game){
this.game = game;
}
public boolean isRunning(){
return running;
}
public void setRunning(boolean b){
this.running = b;
}
public void setPause(boolean b){
this.paused = b;
}
#Override
public void run() {
// TODO Auto-generated method stub
long beginTime;
long ticks = 1000/FPS;
long sleepTime;
while(running){
if(!paused){
beginTime = System.currentTimeMillis();
canvas = null;
try{
canvas = game.holder.lockCanvas();
synchronized(game.getHolder()){
game.draw(canvas);
}
}finally{
if(canvas != null){
game.getHolder().unlockCanvasAndPost(canvas);
}
}
sleepTime = (System.currentTimeMillis() - beginTime)/ticks;
try{
if(sleepTime > 0)
Thread.sleep(sleepTime);
else
Thread.sleep(10);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
}
I'm probably making a very stupid mistake, but no matter how much I scan into the code and change around few bits I can't seem to figure out how exactly to move the sprite. Also, how can I make it so the sprite is centered exactly in any device?
Thank you.
EDIT:
package com.jollygent.tapthepointer;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
public class GameActivity extends Activity {
GamePanel game;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
game = new GamePanel(this);
setContentView(game);
}
#Override
public void onPause(){
super.onPause();
game.getLoop().setPaused(true);
}
#Override
public void onResume(){
super.onResume();
game.getLoop().setPaused(false);
}
}
The problem is that the loop only runs once and once only. Perhaps the GameActivity is the problem?
I have been trying to start a new project and when I went to start up I couldn't get anything working. I have looked at the code for the past few hours and played with it but I can't remember how I fixed this last time it happened.
package org.waldev.canvascollisiontest;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.Menu;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class CollisionTest extends Activity {
private Panel game;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
game = new Panel(this);
setContentView(game);
}
public class Panel extends SurfaceView implements SurfaceHolder.Callback{
Threads thread;
public Panel(Context context) {
super(context);
thread = new Threads(this.getHolder(), this);
setFocusable(true);
}
public void onDraw(Canvas c)
{
c.drawColor(Color.BLUE);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
//when the game starts, run the thread\
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
holder.setFormat(PixelFormat.RGB_565);
thread.setRunning(true);
thread.start();
}
//if its destroyed, then destroy the thread
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
boolean retry = true;
thread.setRunning(false);
while (retry) {
try {
thread.join();
// bitmaps.recycleAll();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
}
}
And the thread:
package org.waldev.canvascollisiontest;
import org.waldev.canvascollisiontest.CollisionTest.Panel;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
public class Threads extends Thread{
SurfaceHolder surfaceHolder;
private Panel game;
private Canvas c;
private boolean isRunning = true;
// desired fps
private final static int MAX_FPS = 24;
// maximum number of frames to be skipped
private final static int MAX_FRAME_SKIPS = 0;
// the frame period
private final static int FRAME_PERIOD = 1000 / MAX_FPS;
public Threads(SurfaceHolder surfaceHolder, Panel panel){
this.surfaceHolder = surfaceHolder;
game = panel;
}
public void setRunning(boolean run){
isRunning = run;
}
public boolean getRunning(){
return isRunning();
}
public SurfaceHolder getSurface(){
return surfaceHolder;
}
#Override
public void run() {
Canvas canvas;
long beginTime; // the time when the cycle begun
long timeDiff; // the time it took for the cycle to execute
int sleepTime; // ms to sleep (<0 if we're behind)
int framesSkipped; // number of frames being skipped
boolean updated = false;
sleepTime = 0;
while (isRunning) {
canvas = null;
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
beginTime = System.currentTimeMillis();
framesSkipped = 0;
if(canvas != null)
{
game.onDraw(canvas);
}
timeDiff = System.currentTimeMillis() - beginTime;
sleepTime = (int)(FRAME_PERIOD - timeDiff);
if (sleepTime > 0) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {}
}
else
{
updated = false;
}
}
} finally {
// in case of an exception the surface is not left in
// an inconsistent state
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
} // end finally
}
}
public boolean isRunning() {
return isRunning;
}
}
I threw some break points in there and it is never calling surfaceCreated in CollisionTest. I know it has to be something stupid that I am missing here, so if you see it let me know. Thanks!
William
I got it working, I forgot to add the:
getHolder().addCallback(this);
to the Constructor for Panel, which is what was causing it to not work. Thanks!
Here is the error.
FastRenderView.java
package framework.impl;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import framework.Game;
public class FastRenderView extends SurfaceView implements Runnable {
Game game;
Bitmap frameBuffer;
Thread renderThread = null;
SurfaceHolder holder;
volatile boolean running = false;
public FastRenderView(Game game, Bitmap frameBuffer) {
super(game);
this.game = game;
this.frameBuffer = frameBuffer;
this.holder = getHolder();
}
#Override
public void run() {
Rect dstRect = new Rect();
long startTime = System.nanoTime();
while(running) {
if(!holder.getSurface().isValid()) {
continue;
}
float deltaTime = (System.nanoTime() - startTime) / 1000000000.0f;
startTime = System.nanoTime();
game.getScreen().update(deltaTime);
game.getScreen().present(deltaTime);
Canvas canvas = holder.lockCanvas();
canvas.getClipBounds(dstRect);
canvas.drawBitmap(frameBuffer, null, dstRect, null);
holder.unlockCanvasAndPost(canvas);
}
}
public void resume() {
running = true;
renderThread = new Thread(this);
renderThread.start();
}
public void pause() {
running = false;
while(true) {
try {
renderThread.join();
break;
} catch(Exception e) {
// retry
}
}
}
}
The problem is that on line 19 I get the error that is showed above for 'super(game);'
The question is how do I fix this?
If you need more information then let me know!!!
Thanks for your help!
Take a look at this reference: http://developer.android.com/reference/android/view/SurfaceView.htmlhttp://developer.android.com/reference/android/view/SurfaceView.html
When you call super(), you are passing the game object the the parent constructor, which is that of SurfaceView. The only single-parameter constructor implemented by SurfaceView takes a Context Object. Does the Game class inherit from Context somewhere in the inheritance chain?
If no, then there's your problem. If yes, post the code for the Game class.