I am trying to render a 2D square, but my program crashes. I think my order of methods is incorrect. I am using LWJGL3, with the jars Lwjgl, GLFW, and OpenGL. The stacktrace shows the error is an EXCEPTION_ACCESS_VIOLATION, and the error is at the first openGL function depending on which one is first (with current code it is GL20.glGetAttribLocation() (following the guid here: https://github.com/SilverTiger/lwjgl3-tutorial/wiki/Rendering)
I am also not using legacyGL
If your having this problem:
add the lines GLFW.makeContextCurrent(window) and Gl.createCapabilities()
Main:
public class DungeonRunners {
private double lastTick;
private float timeCount;
private int fps;
private int fpsCount;
private int ups;
private int upsCount;
public static void main(String[] args) {
System.out.println("LWJGL Version: " + Version.getVersion());
int width = 1240;
int height = 720;
boolean legacyGL = false;
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if(arg.equals("width:")) {
try {
width = Integer.parseInt(args[i+1]);
i++;
} catch (NumberFormatException ignored) { }
} else if(arg.equals("height:")) {
try {
height = Integer.parseInt(args[i+1]);
} catch (NumberFormatException ignored) { }
} else if(arg.equals("-useLegacyGL")) {
legacyGL = true;
}
}
DungeonRunners dungeonRunners = new DungeonRunners();
dungeonRunners.start(width, height, legacyGL);
}
private void start(int width, int height, Boolean legacyGL) {
long window;
GLFW.glfwInit();
if(!legacyGL) {
GLFW.glfwDefaultWindowHints();
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 2);
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE);
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_FORWARD_COMPAT, GLFW.GLFW_TRUE);
window = GLFW.glfwCreateWindow(width, height, "Dungeon Runners", MemoryUtil.NULL, MemoryUtil.NULL);
} else {
GLFW.glfwDefaultWindowHints();
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 2);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 1);
window = GLFW.glfwCreateWindow(width, height, "Dungeon Runners", MemoryUtil.NULL, MemoryUtil.NULL);
}
RenderEngine engine = new RenderEngine(legacyGL);
while(!GLFW.glfwWindowShouldClose(window)) {
update();
engine.frame();
}
}
private void update() {
if (timeCount > 1f) {
fps = fpsCount;
fpsCount = 0;
ups = upsCount;
upsCount = 0;
timeCount -= 1f;
}
}
private float getDelta() {
double time = getTime();
float delta = (float) (time - lastTick);
lastTick = time;
timeCount += delta;
return delta;
}
public double getTime() {
return System.nanoTime() / 1000000000.0;
}
private void updateFPS() {
fpsCount++;
}
private void updateUPS() {
upsCount++;
}
}
The code is pretty explanatory, here is my RenderEngine class:
public class RenderEngine {
private int shaderProgram;
public RenderEngine(Boolean legacyGL) {
setVertexAttribs();
bindImage();
int vao = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vao);
setupShaders(legacyGL);
GL20.glUseProgram(shaderProgram);
setUniformVars();
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 3);
}
private void bindImage() {
try (MemoryStack stack = MemoryStack.stackPush()) {
FloatBuffer vertices = stack.mallocFloat(3 * 6);
vertices.put(-0.6f).put(-0.4f).put(0f).put(1f).put(0f).put(0f);
vertices.put(0.6f).put(-0.4f).put(0f).put(0f).put(1f).put(0f);
vertices.put(0f).put(0.6f).put(0f).put(0f).put(0f).put(1f);
vertices.flip();
int vbo = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertices, GL15.GL_STATIC_DRAW);
MemoryStack.stackPop();
}
}
public void frame() {
}
private void setUniformVars() {
int uniModel = GL20.glGetUniformLocation(shaderProgram, "model");
UtilMatrix4f model = new UtilMatrix4f();
GL20.glUniformMatrix4fv(uniModel, false, model.getBuffer());
int uniView = GL20.glGetUniformLocation(shaderProgram, "view");
UtilMatrix4f view = new UtilMatrix4f();
GL20.glUniformMatrix4fv(uniView, false, view.getBuffer());
int uniProjection = GL20.glGetUniformLocation(shaderProgram, "projection");
float ratio = 640f / 480f;
UtilMatrix4f projection = UtilMatrix4f.orthographic(-ratio, ratio, -1f, 1f, -1f, 1f);
GL20.glUniformMatrix4fv(uniProjection, false, projection.getBuffer());
}
private void setVertexAttribs() {
int floatSize = 4;
int posAttrib = GL20.glGetAttribLocation(shaderProgram, "position");
GL20.glEnableVertexAttribArray(posAttrib);
GL20.glVertexAttribPointer(posAttrib, 3, GL11.GL_FLOAT, false, 6 * floatSize, 0);
int colAttrib = GL20.glGetAttribLocation(shaderProgram, "color");
GL20.glEnableVertexAttribArray(colAttrib);
GL20.glVertexAttribPointer(colAttrib, 3, GL11.GL_FLOAT, false, 6 * floatSize, 3 * floatSize);
}
private void setupShaders(boolean legacyGL) {
int vertexShader = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
if(legacyGL)
GL20.glShaderSource(vertexShader, "src\\main\\java\\bigbade\\dungeonrunners\\renderer\\shaders\\legacyVertexShader.txt");
else
GL20.glShaderSource(vertexShader, "src\\main\\java\\bigbade\\dungeonrunners\\renderer\\shaders\\vertexShader.txt");
GL20.glCompileShader(vertexShader);
int status = GL20.glGetShaderi(vertexShader, GL20.GL_COMPILE_STATUS);
if (status != GL11.GL_TRUE) {
throw new RuntimeException(GL20.glGetShaderInfoLog(vertexShader));
}
int fragmentShader = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
if(legacyGL)
GL20.glShaderSource(vertexShader, "src\\main\\java\\bigbade\\dungeonrunners\\renderer\\shaders\\legacyFragmentShader.txt");
else
GL20.glShaderSource(fragmentShader, "src\\main\\java\\bigbade\\dungeonrunners\\renderer\\shaders\\fragmentShader.txt");
GL20.glCompileShader(fragmentShader);
status = GL20.glGetShaderi(fragmentShader, GL20.GL_COMPILE_STATUS);
if (status != GL11.GL_TRUE) {
throw new RuntimeException(GL20.glGetShaderInfoLog(fragmentShader));
}
shaderProgram = GL20.glCreateProgram();
GL20.glAttachShader(shaderProgram, vertexShader);
GL20.glAttachShader(shaderProgram, fragmentShader);
GL30.glBindFragDataLocation(shaderProgram, 0, "fragColor");
GL20.glLinkProgram(shaderProgram);
status = GL20.glGetProgrami(shaderProgram, GL20.GL_LINK_STATUS);
if (status != GL11.GL_TRUE) {
throw new RuntimeException(GL20.glGetProgramInfoLog(shaderProgram));
}
}
}
Related
Trying to make a motion detection app based on this project. The intention is to make the app take pictures when motion is detected by comparing two images. Up to this part, the app is working fine.
Requirement:
To specify area of detection by a custom view. So that, the pictures will be captured only if a motion is detected inside the defined area by calculating the detection area.
What I have done so far:
Created a movable custom view, like a crop view of which the dimensions (Rect) are saved in the preference each time when the view is moved.
What is not working:
The motion detection from inside the custom view is not working. I believe that the bitmaps must be cropped according to the size of the custom view to do the comparison.
In the detection thread I tried setting the width and height from the preference like :
private int width = Prefe.DetectionArea.width();
private int height = Prefe.DetectionArea.height();
But it didn't work. Please help me by explaining how this could be achieved so that the motion detection will happen according to the size of the custom view. Any help is appreciated.
Project Source Code: https://drive.google.com/drive/folders/0B7-oKqt7w49mbTR6VWZYVURmVms
MotionDetectionActivity.java
public class MotionDetectionActivity extends SensorsActivity {
private static final String TAG = "MotionDetectionActivity";
private static long mReferenceTime = 0;
private static IMotionDetection detector = null;
public static MediaPlayer song;
public static Vibrator mVibrator;
private static SurfaceView preview = null;
private static SurfaceHolder previewHolder = null;
private static Camera camera = null;
private static boolean inPreview = false;
private static AreaDetectorView mDetector;
private static FrameLayout layoutDetectorArea;
static FrameLayout layoutMain;
static View mView;
private static volatile AtomicBoolean processing = new AtomicBoolean(false);
/**
* {#inheritDoc}
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.main);
mVibrator = (Vibrator)this.getSystemService(VIBRATOR_SERVICE);
layoutMain=(FrameLayout)findViewById(R.id.layoutMain);
preview = (SurfaceView) findViewById(R.id.preview);
previewHolder = preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mView=layoutMain;
mDetector= (AreaDetectorView) findViewById(R.id.viewDetector);
layoutDetectorArea=(FrameLayout) findViewById(R.id.layoutDetectArea);
ToggleButton toggle = (ToggleButton) findViewById(R.id.simpleToggleButton);
toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
// The toggle is enabled
} else {
// The toggle is disabled
}
}
});
if (Preferences.USE_RGB) {
detector = new RgbMotionDetection();
} else if (Preferences.USE_LUMA) {
detector = new LumaMotionDetection();
} else {
// Using State based (aggregate map)
detector = new AggregateLumaMotionDetection();
}
}
/**
* {#inheritDoc}
*/
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
/**dd:
* Song play # 1
* Camera callback
*
* {#inheritDoc}
*/
#Override
public void onPause() {
super.onPause();
if(song!=null && song.isPlaying())
{
song.stop();}
camera.setPreviewCallback(null);
if (inPreview) camera.stopPreview();
inPreview = false;
camera.release();
camera = null;
}
/**
* {#inheritDoc}
*/
#Override
public void onResume() {
super.onResume();
camera = Camera.open();
}
private PreviewCallback previewCallback = new PreviewCallback() {
/**
* {#inheritDoc}
*/
#Override
public void onPreviewFrame(byte[] data, Camera cam) {
if (data == null) return;
Camera.Size size = cam.getParameters().getPreviewSize();
if (size == null) return;
if (!GlobalData.isPhoneInMotion()) {
DetectionThread thread = new DetectionThread(data, size.width, size.height);
thread.start();
}
}
};
private SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {
/**
* {#inheritDoc}
*/
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera.setPreviewDisplay(previewHolder);
camera.setPreviewCallback(previewCallback);
} catch (Throwable t) {
Log.e("Prek", "Exception in setPreviewDisplay()", t);
}
}
/**
* {#inheritDoc}
*/
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if(camera != null) {
Camera.Parameters parameters = camera.getParameters();
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
Camera.Size size = getBestPreviewSize(width, height, parameters);
if (size != null) {
parameters.setPreviewSize(size.width, size.height);
Log.d(TAG, "Using width=" + size.width + " height=" + size.height);
}
camera.setParameters(parameters);
camera.startPreview();
inPreview = true;
}
//AreaDetectorView.InitDetectionArea();
}
/**
* {#inheritDoc}
*/
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// Ignore
}
};
private static Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) {
Camera.Size result = null;
for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
if (size.width <= width && size.height <= height) {
if (result == null) {
result = size;
} else {
int resultArea = result.width * result.height;
int newArea = size.width * size.height;
if (newArea > resultArea) result = size;
}
}
}
return result;
}
//***************Detection Class******************//
private final class DetectionThread extends Thread {
private byte[] data;
private int width;
private int height;
public DetectionThread(byte[] data, int width, int height) {
this.data = data;
this.width = width;
this.height = height;
}
/**
* {#inheritDoc}
*/
#Override
public void run() {
if (!processing.compareAndSet(false, true)) return;
// Log.d(TAG, "BEGIN PROCESSING...");
try {
// Previous frame
int[] pre = null;
if (Preferences.SAVE_PREVIOUS) pre = detector.getPrevious();
// Current frame (with changes)
// long bConversion = System.currentTimeMillis();
int[] img = null;
if (Preferences.USE_RGB) {
img = ImageProcessing.decodeYUV420SPtoRGB(data, width, height);
} else {
img = ImageProcessing.decodeYUV420SPtoLuma(data, width, height);
}
// Current frame (without changes)
int[] org = null;
if (Preferences.SAVE_ORIGINAL && img != null) org = img.clone();
if (img != null && detector.detect(img, width, height)) {
// The delay is necessary to avoid taking a picture while in
// the
// middle of taking another. This problem can causes some
// phones
// to reboot.
long now = System.currentTimeMillis();
if (now > (mReferenceTime + Preferences.PICTURE_DELAY)) {
mReferenceTime = now;
//mVibrator.vibrate(10);
Bitmap previous = null;
if (Preferences.SAVE_PREVIOUS && pre != null) {
if (Preferences.USE_RGB) previous = ImageProcessing.rgbToBitmap(pre, width, height);
else previous = ImageProcessing.lumaToGreyscale(pre, width, height);
}
Bitmap original = null;
if (Preferences.SAVE_ORIGINAL && org != null) {
if (Preferences.USE_RGB) original = ImageProcessing.rgbToBitmap(org, width, height);
else original = ImageProcessing.lumaToGreyscale(org, width, height);
}
Bitmap bitmap = null;
if (Preferences.SAVE_CHANGES) {
if (Preferences.USE_RGB) bitmap = ImageProcessing.rgbToBitmap(img, width, height);
else bitmap = ImageProcessing.lumaToGreyscale(img, width, height);
}
Log.i(TAG, "Saving.. previous=" + previous + " original=" + original + " bitmap=" + bitmap);
Looper.prepare();
new SavePhotoTask().execute(previous, original, bitmap);
} else {
Log.i(TAG, "Not taking picture because not enough time has passed since the creation of the Surface");
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
processing.set(false);
}
// Log.d(TAG, "END PROCESSING...");
processing.set(false);
}
};
private static final class SavePhotoTask extends AsyncTask<Bitmap, Integer, Integer> {
/**
* {#inheritDoc}
*/
#Override
protected Integer doInBackground(Bitmap... data) {
for (int i = 0; i < data.length; i++) {
Bitmap bitmap = data[i];
String name = String.valueOf(System.currentTimeMillis());
if (bitmap != null) save(name, bitmap);
}
return 1;
}
private void save(String name, Bitmap bitmap) {
File photo = new File(Environment.getExternalStorageDirectory(), name + ".jpg");
if (photo.exists()) photo.delete();
try {
FileOutputStream fos = new FileOutputStream(photo.getPath());
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.close();
} catch (java.io.IOException e) {
Log.e("PictureDemo", "Exception in photoCallback", e);
}
}
}
}
AreaDetectorView.java
public class AreaDetectorView extends LinearLayout {
public static int Width;
public static int Height;
private static Paint BoxPaint = null;
private static Paint TextPaint = null;
private static Paint ArrowPaint = null;
private static Path mPath = null;
private static Rect mRect = null;
private static int lastX, lastY = 0;
private static boolean mBoxTouched = false;
private static boolean mArrowTouched = false;
private static Context mContext;
private static int ArrowWidth = 0;
private static Paint BoxPaint2 = null;
public AreaDetectorView(Context context) {
super(context);
mContext = context;
}
//attrs was not there
public AreaDetectorView(Context context, AttributeSet attrs) {
super(context,attrs);
mContext = context;
// TODO Auto-generated constructor stub
if (!this.getRootView().isInEditMode()) {
ArrowWidth =GetDisplayPixel(context, 30);
}
//InitDetectionArea();
InitMemberVariables();
setWillNotDraw(false);
}
public static int GetDisplayPixel(Context paramContext, int paramInt)
{
return (int)(paramInt * paramContext.getResources().getDisplayMetrics().density + 0.5F);
}
public static void InitMemberVariables() {
if (BoxPaint == null) {
BoxPaint = new Paint();
BoxPaint.setAntiAlias(true);
BoxPaint.setStrokeWidth(2.0f);
//BoxPaint.setStyle(Style.STROKE);
BoxPaint.setStyle(Style.FILL_AND_STROKE);
BoxPaint.setColor(ContextCompat.getColor(mContext, R.color.bwff_60));
}
if (ArrowPaint == null) {
ArrowPaint = new Paint();
ArrowPaint.setAntiAlias(true);
ArrowPaint.setColor(ContextCompat.getColor(mContext,R.color.redDD));
ArrowPaint.setStyle(Style.FILL_AND_STROKE);
}
if (TextPaint == null) {
TextPaint = new Paint();
TextPaint.setColor(ContextCompat.getColor(mContext,R.color.yellowL));
TextPaint.setTextSize(16);
//txtPaint.setTypeface(lcd);
TextPaint.setStyle(Style.FILL_AND_STROKE);
}
if (mPath == null) {
mPath = new Path();
} else {
mPath.reset();
}
if (mRect == null) {
mRect = new Rect();
}
if (BoxPaint2 == null) {
BoxPaint2 = new Paint();
BoxPaint2.setAntiAlias(true);
BoxPaint2.setStrokeWidth(2.0f);
//BoxPaint.setStyle(Style.STROKE);
BoxPaint2.setStyle(Style.STROKE);
BoxPaint2.setColor(ContextCompat.getColor(mContext,R.color.bwff_9e));
}
}
public static void InitDetectionArea() {
try {
int w = Prefe.DetectionArea.width();
int h = Prefe.DetectionArea.height();
int x = Prefe.DetectionArea.left;
int y = Prefe.DetectionArea.top;
// ver 2.6.0
if (Prefe.DetectionArea.left == 1
&& Prefe.DetectionArea.top == 1
&& Prefe.DetectionArea.right == 1
&& Prefe.DetectionArea.bottom == 1) {
w = Prefe.DisplayWidth / 4;
h = Prefe.DisplayHeight / 3;
// ver 2.5.9
w = Width / 4;
h = Height / 3;
Prefe.DetectorWidth = w; //UtilGeneralHelper.GetDisplayPixel(this, 100);
Prefe.DetectorHeight = h; //UtilGeneralHelper.GetDisplayPixel(this, 100);
x = (Prefe.DisplayWidth / 2) - (w / 2);
y = (Prefe.DisplayHeight / 2) - (h / 2);
// ver 2.5.9
x = (Width / 2) - (w / 2);
y = (Height / 2) - (h / 2);
}
//Prefe.DetectionArea = new Rect(x, x, x + Prefe.DetectorWidth, x + Prefe.DetectorHeight);
Prefe.DetectionArea = new Rect(x, y, x + w, y + h);
Prefe.gDetectionBitmapInt = new int[Prefe.DetectionArea.width() * Prefe.DetectionArea.height()];
Prefe.gDetectionBitmapIntPrev = new int[Prefe.DetectionArea.width() * Prefe.DetectionArea.height()];
} catch (Exception e) {
e.printStackTrace();
}
}
public static void SetDetectionArea(int x, int y, int w, int h) {
try {
Prefe.DetectionArea = new Rect(x, y, w, h);
} catch (Exception e) {
e.printStackTrace();
}
}
private void DrawAreaBox(Canvas canvas) {
try {
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void dispatchDraw(Canvas canvas) {
try {
if (this.getRootView().isInEditMode()) {
super.dispatchDraw(canvas);
return;
}
//canvas.save(Canvas.MATRIX_SAVE_FLAG);
//Prefe.DetectionAreaOrient = UtilGeneralHelper.GetDetectRectByOrientation();
canvas.drawColor(0);
mPath.reset();
canvas.drawRect(Prefe.DetectionArea, BoxPaint);
mPath.moveTo(Prefe.DetectionArea.right - ArrowWidth, Prefe.DetectionArea.bottom);
mPath.lineTo(Prefe.DetectionArea.right, Prefe.DetectionArea.bottom - ArrowWidth);
mPath.lineTo(Prefe.DetectionArea.right, Prefe.DetectionArea.bottom);
mPath.lineTo(Prefe.DetectionArea.right - ArrowWidth, Prefe.DetectionArea.bottom);
mPath.close();
canvas.drawPath(mPath, ArrowPaint);
mPath.reset();
//canvas.drawRect(Prefe.DetectionAreaOrient, BoxPaint2);
//canvas.drawRect(Prefe.DetectionAreaOrientPort, BoxPaint2);
TextPaint.setTextSize(16);
//TextPaint.setLetterSpacing(2);
TextPaint.setColor(ContextCompat.getColor(mContext,R.color.bwff));
TextPaint.getTextBounds(getResources().getString(R.string.str_detectarea), 0, 1, mRect);
canvas.drawText(getResources().getString(R.string.str_detectarea),
Prefe.DetectionArea.left + 4,
Prefe.DetectionArea.top + 4 + mRect.height(),
TextPaint);
int recH = mRect.height();
TextPaint.setStrokeWidth(1.2f);
TextPaint.setTextSize(18);
TextPaint.setColor(ContextCompat.getColor(mContext,R.color.redD_9e));
TextPaint.getTextBounds(getResources().getString(R.string.str_dragandmove), 0, 1, mRect);
canvas.drawText(getResources().getString(R.string.str_dragandmove),
Prefe.DetectionArea.left + 4,
Prefe.DetectionArea.top + 20 + mRect.height()*2,
TextPaint);
TextPaint.getTextBounds(getResources().getString(R.string.str_scalearea), 0, 1, mRect);
canvas.drawText(getResources().getString(R.string.str_scalearea),
Prefe.DetectionArea.left + 4,
Prefe.DetectionArea.top + 36 + mRect.height()*3,
TextPaint);
super.dispatchDraw(canvas);
//canvas.restore();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onDraw(Canvas canvas) {
try {
super.onDraw(canvas);
invalidate();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
boolean retValue = true;
int X = (int)event.getX();
int Y = (int)event.getY();
//AppMain.txtLoc.setText(String.valueOf(X) + ", " + String.valueOf(Y));
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mBoxTouched = TouchedInBoxArea(X, Y);
//AppMain.txtLoc.setText("BoxTouched: " + String.valueOf(mBoxTouched));
if (!mBoxTouched) break;
lastX = X;
lastY = Y;
BoxPaint.setStyle(Style.FILL_AND_STROKE);
BoxPaint.setColor(ContextCompat.getColor(mContext,R.color.redD_9e));
mArrowTouched = TouchedInArrow(X, Y);
//AppMain.txtLoc.setText("ArrowTouched: " + String.valueOf(mBoxTouched));
if (mArrowTouched) {
ArrowPaint.setColor(ContextCompat.getColor(mContext,R.color.bwff_9e));
}
break;
case MotionEvent.ACTION_MOVE:
if (!mBoxTouched) break;
int moveX = X - lastX;
int moveY = Y - lastY;
//AppMain.txtLoc.setText("Move X, Y: " + String.valueOf(moveX) + "," + String.valueOf(moveY));
if (!mArrowTouched) {
if (Prefe.DetectionArea.left + moveX < 0) {
break;
}
// if (Prefe.DetectionArea.right + moveX > Prefe.gDisplay.getWidth()) {
// break;
// }
// ver 2.5.9
if (Prefe.DetectionArea.right + moveX > Width) {
break;
}
if (Prefe.DetectionArea.top + moveY < 0) {
break;
}
// if (Prefe.DetectionArea.bottom + moveY > Prefe.gDisplay.getHeight()) {
// break;
// }
// ver 2.5.9
if (Prefe.DetectionArea.bottom + moveY > Height) {
break;
}
}
if (mArrowTouched) {
if ((Prefe.DetectionArea.width() + moveX) < ArrowWidth * 2){
break;
}
if ((Prefe.DetectionArea.height() + moveY) < ArrowWidth * 2) {
break;
}
Prefe.DetectionArea.right += moveX;
Prefe.DetectionArea.bottom += moveY;
//Log.i("DBG", "W,H: " + String.valueOf(Prefe.DetectionArea.width()) + "," + String.valueOf(Prefe.DetectionArea.height()));
} else {
Prefe.DetectionArea.left += moveX;
Prefe.DetectionArea.right += moveX;
Prefe.DetectionArea.top += moveY;
Prefe.DetectionArea.bottom += moveY;
}
lastX = X;
lastY = Y;
//AppMain.txtLoc.setText(String.valueOf(Prefe.DetectionArea.left) + ", " + String.valueOf(Prefe.DetectionArea.top));
break;
case MotionEvent.ACTION_UP:
mBoxTouched = false;
mArrowTouched = false;
//BoxPaint.setStyle(Style.STROKE);
BoxPaint.setStyle(Style.FILL_AND_STROKE);
BoxPaint.setColor(ContextCompat.getColor(mContext,R.color.bwff_60));
ArrowPaint.setColor(ContextCompat.getColor(mContext,R.color.redDD));
//AppMain.txtLoc.setText(String.valueOf(Prefe.DetectionArea.left) + ", " + String.valueOf(Prefe.DetectionArea.top));
if (Prefe.DetectionArea.left < 0) {
Prefe.DetectionArea.left = 0;
}
// if (Prefe.DetectionArea.right > Prefe.gDisplay.getWidth()) {
// Prefe.DetectionArea.right = Prefe.gDisplay.getWidth();
// }
// ver 2.5.9
if (Prefe.DetectionArea.right > Width) {
Prefe.DetectionArea.right = Width;
}
if (Prefe.DetectionArea.top < 0) {
Prefe.DetectionArea.top = 0;
}
// if (Prefe.DetectionArea.bottom > Prefe.gDisplay.getHeight()) {
// Prefe.DetectionArea.bottom = Prefe.gDisplay.getHeight();
// }
if (Prefe.DetectionArea.bottom > Height) {
Prefe.DetectionArea.bottom = Height;
}
Prefe.gDetectionBitmapInt = new int[Prefe.DetectionArea.width() * Prefe.DetectionArea.height()];
Prefe.gDetectionBitmapIntPrev = new int[Prefe.DetectionArea.width() * Prefe.DetectionArea.height()];
//Prefe.gDetectionBitmapInt = null;
//Prefe.gDetectionBitmapIntPrev = null;
String area = String.valueOf(Prefe.DetectionArea.left)
+ "," + String.valueOf(Prefe.DetectionArea.top)
+ "," + String.valueOf(Prefe.DetectionArea.right)
+ "," + String.valueOf(Prefe.DetectionArea.bottom);
// UtilGeneralHelper.SavePreferenceSetting(Prefe.gContext, Prefe.PREF_DETECTION_AREA_KEY, area);
//Saving the value
SharedPrefsUtils.setStringPreference(mContext.getApplicationContext(), Prefe.PREF_DETECTION_AREA_KEY, area);
Log.v("TAG", SharedPrefsUtils.getStringPreference(mContext.getApplicationContext(),Prefe.PREF_DETECTION_AREA_KEY));
break;
}
invalidate();
return retValue;
}
private boolean TouchedInBoxArea(int x, int y) {
boolean retValue = false;
try {
if (x > Prefe.DetectionArea.left && x < Prefe.DetectionArea.right) {
if (y > Prefe.DetectionArea.top && y < Prefe.DetectionArea.bottom) {
retValue = true;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return retValue;
}
private boolean TouchedInArrow(int x, int y) {
boolean retValue = false;
try {
if (x > Prefe.DetectionArea.right - ArrowWidth && x < Prefe.DetectionArea.right) {
if (y > Prefe.DetectionArea.bottom - ArrowWidth && y < Prefe.DetectionArea.bottom) {
retValue = true;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return retValue;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
Width = width;
Height = height;
InitDetectionArea();
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
for (int i = 0; i < this.getChildCount()-1; i++){
(this.getChildAt(i)).layout(l, t, r, b);
}
if (changed) {
// check width height
if (r != Width || b != Height) {
// size does not match
}
}
}
}
Prefe.java
public class Prefe extends Application{
...
public static final String PREF_DETECTION_AREA_KEY = "pref_detection_area_key";
}
static{
...
DetectionArea = new Rect(1, 1, 1, 1);
}
}
I have a sprite that collides with obstacle, but i have a problem with the score in the top of my screen.
In the update of my class, The collisions are specified by an array, but when it collides with an object, the score is still growing and I can not stop it. this is my code:
private Array<Polen> polen;
private Score score;
public PlayState(GameStateManager gsm) {
super(gsm);
score = new Score(110, 310);
polen = new Array<Polen>();
for(int i = 1; i <= COUNT; i++){
polen.add(new Polen(i * (Polen.WIDTH)));
}
}
#Override
public void update(float dt) {
handleInput();
for(int i = 0; i < polen.size; i++){
Polen pol= polen.get(i);
if(pol.collides(aliado.getBounds())) {
pol.changeExplosion();
flagScore = 1;
}
if (pol.collides(aliado.getBounds())==false){
flagScore = 0;
}
}
if (flagScore == 1){
Score.count++;
flagScore=0;
//auxCount = Score.count +1;
}
score.update(dt);
updateGround();
cam.update();
}
Score Class:
public class Score {
private static final int MOVEMENT = 70;
private Vector3 position;
private Vector3 velocity;
private Rectangle bounds;
private Texture texture;
public Score(int x, int y){
position = new Vector3(x, y, 0);
velocity = new Vector3(0, 0, 0);
texture = new Texture("score0.png");
bounds = new Rectangle(x, y, ((texture.getWidth())), texture.getHeight());
}
public void update(float dt){//code for move the score for top of screen:
if(position.y > 0)
velocity.add(0, 0, 0);
velocity.scl(dt);
position.add(MOVEMENT * dt, velocity.y, 0);
if(position.y < 0)
position.y = 0;
velocity.scl(1/dt);
bounds.setPosition(position.x, position.y);
}
public Vector3 getPosition() {
return position;
}
public Texture getTexture() {
return texture;
}
public void setTexture(Texture texture) {
this.texture = texture;
}
public Vector3 getVelocity() {
return velocity;
}
public void setVelocity(Vector3 velocity) {
this.velocity = velocity;
}
public Rectangle getBounds(){
return bounds;
}
public void setBounds(Rectangle bounds) {
this.bounds = bounds;
}
public void dispose(){
texture.dispose();
}
}
In pol.changeExplosion() you should add a boolean to mark the object as done.
public class Polen {
private boolean exploded = false;
public void changeExplosion() {
// ...
exploded = true;
// ...
}
public boolean isExploded() {
return exploded;
}
}
Then, in your update function you can use this flag to determine if the score should stop being incremented.
for(int i = 0; i < polen.size; i++) {
Polen pol= polen.get(i);
if(pol.collides(aliado.getBounds()) && !pol.isExploded()) {
pol.changeExplosion();
flagScore = 1;
}
else if (!pol.collides(aliado.getBounds())) {
flagScore = 0;
}
}
I am currently testing something out with GLSL, but now whenever I use shaders, my texture doesn't show up on the screen. I have 2 classes. It works without the shaders though...
Main Class
public class Main {
private static final int WIDTH = 1280;
private static final int HEIGHT = 720;
private static int shaderProgram;
private static int vertexShader;
private static int fragmentShader;
private static Terrain terrain;
public static void main(String[] args) {
initDisplay();
initGL();
terrain = new Terrain();
terrain.createTerrain();
createShader();
gameLoop();
removeShader();
}
private static void gameLoop() {
while (!Display.isCloseRequested()) {
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
terrain.drawTerrain();
glUseProgram(0);
Display.update();
Display.sync(60);
}
}
private static void initGL() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, WIDTH, 0, HEIGHT, -1, 1);
glMatrixMode(GL_MODELVIEW);
glDisable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glClearColor(0, 0, 0, 1);
}
private static void initDisplay() {
try {
Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
}
}
private static void createShader() {
shaderProgram = glCreateProgram();
vertexShader = glCreateShader(GL_VERTEX_SHADER);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
StringBuilder vertexShaderSource = new StringBuilder();
StringBuilder fragmentShaderSource = new StringBuilder();
try {
BufferedReader reader = new BufferedReader(new FileReader("src/me/mateo226/shaders/vertexShader.txt"));
String line;
while ((line = reader.readLine()) != null) {
vertexShaderSource.append(line).append("\n");
}
reader.close();
} catch (IOException e) {
System.err.println("Vertex shader wasn't loaded properly!");
Display.destroy();
System.exit(1);
}
try {
BufferedReader reader = new BufferedReader(new FileReader("src/me/mateo226/shaders/fragmentShader.txt"));
String line;
while ((line = reader.readLine()) != null) {
fragmentShaderSource.append(line).append("\n");
}
reader.close();
} catch (IOException e) {
System.err.println("Fragment shader wasn't loaded properly!");
Display.destroy();
System.exit(1);
}
glShaderSource(vertexShader, vertexShaderSource);
glCompileShader(vertexShader);
if (glGetShader(vertexShader, GL_COMPILE_STATUS) == GL_FALSE) {
System.err.println("Vertex shader not compiled!");
}
glShaderSource(fragmentShader, fragmentShaderSource);
glCompileShader(fragmentShader);
if (glGetShader(fragmentShader, GL_COMPILE_STATUS) == GL_FALSE) {
System.err.println("Fragment shader not compiled!");
}
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glValidateProgram(shaderProgram);
}
private static void removeShader() {
glDeleteProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
Display.destroy();
}
}
Terrain Class
public class Terrain {
private static List<Tile> tiles = new ArrayList<Tile>();
public Terrain() {
}
public void createTerrain() {
Random rand = new Random();
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 15; j++) {
int r = rand.nextInt(2);
tiles.add(new Tile(i * 64, j * 64, r));
}
}
}
public void drawTerrain() {
for (Tile t : tiles) {
t.draw();
}
}
}
class Tile {
int type = 0;
private float x = 0;
private float y = 0;
private float width = 64;
private float height = 64;
private Texture tex;
public Tile(float x, float y, int type) {
this.type = type;
this.x = x;
this.y = y;
try {
if (this.type == 1) {
tex = TextureLoader.getTexture("PNG", new FileInputStream(new File("res/grass.png")));
} else {
tex = TextureLoader.getTexture("PNG", new FileInputStream(new File("res/grass.png")));
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void draw() {
tex.bind();
glBegin(GL_QUADS);
{
glTexCoord2f(0, 0);
glVertex2f(x, y);
glTexCoord2f(0, 1);
glVertex2f(x, y + height);
glTexCoord2f(1, 1);
glVertex2f(x + width, y + height);
glTexCoord2f(1, 0);
glVertex2f(x + width, y);
}
glEnd();
}
}
While it may seem like a lot of code, it really isn't, just a simple program. However I am still unable to figure out what makes it not work. My vertex shader just has:
gl_Position = ftransform();
I tried adding gl_FragColor to the fragment shader but it doesn't help.
Cheers!
If you don't want to do anything with the texture e.g. lighting, you just have to assign texture2D(TexSampler, TexCoord) to the gl_FragColor in your frag shader.
That's because fragment shader will take care of each pixel (fragment) on screen (in current shader program).
If you don't assign any value to the gl_FragColor variable, nothing will drawn. What you want is to assign your texture (a bunch of pixels) to the gl_FragColor and you're good to go.
Hello I wan't to do heightmap based game and I have optimization problem. I acctualy rendering in DisplayList but when I want to render heightmap 512x512 I have only 20-30 fps. I tried something in vbo but that don't work. Here is my sourcecode to display lists rendering:
public class Heightmap {
public static final Vector2f CHUNK_XZ = new Vector2f(256, 256);
public int CHUNK_ID;
private float[][] chunk_data = null;
private Vector3f[][] chunk_color_data = null;
private Vector3f pos;
private Vector3f scale = new Vector3f(10, 10, 10);
private boolean visible = true;
private int displayID;
private Texture texture;
public Heightmap(Vector3f pos) {
this.pos = pos;
chunk_data = new float[(int) CHUNK_XZ.x][(int) CHUNK_XZ.y];
chunk_color_data = new Vector3f[(int) CHUNK_XZ.x][(int) CHUNK_XZ.y];
for(int x = 0; x < chunk_data.length; x++) {
for(int y = 0; y < chunk_data[0].length; y++) {
chunk_data[x][y] = 1.0f;
chunk_color_data[x][y] = new Vector3f(0f, 0f, (float) Math.random());
}
}
try {
texture = TextureLoader.getTexture("jpg", new FileInputStream(new File("grassy.jpg")));
} catch (IOException e) {
e.printStackTrace();
}
displayID = glGenLists(1);
GL11.glNewList(displayID, GL11.GL_COMPILE);
texture.bind();
GL11.glPushMatrix();
GL11.glScalef(scale.x, scale.y, scale.z);
GL11.glBegin(GL11.GL_QUADS);
int heightmapExaggeration = 10;
for(int x=0; x < chunk_data.length; x++) {
for(int y=0; y < chunk_data[x].length; y++) {
GL11.glColor3f(chunk_color_data[x][y].getX(), chunk_color_data[x][y].getY(), chunk_color_data[x][y].getZ());
GL11.glTexCoord2f(0, 0);
GL11.glVertex3f(x*0.25f, getHeightAt(x, y)*heightmapExaggeration, y*0.25f);
GL11.glTexCoord2f(1, 0);
GL11.glVertex3f((x+1)*0.25f, getHeightAt(x+1, y)*heightmapExaggeration, y*0.25f);
GL11.glTexCoord2f(1, 1);
GL11.glVertex3f((x+1)*0.25f, getHeightAt(x+1, y+1)*heightmapExaggeration, (y+1)*0.25f);
GL11.glTexCoord2f(0, 1);
GL11.glVertex3f(x*0.25f, getHeightAt(x, y+1)*heightmapExaggeration, (y+1)*0.25f);
}
}
GL11.glEnd();
GL11.glPopMatrix();
texture.release();
GL11.glEndList();
}
public Chunk(float[][] chunk_data, Vector3f[][] chunk_color_data, Vector3f pos) {
this.chunk_data = chunk_data;
this.chunk_color_data = chunk_color_data;
this.pos = pos;
try {
texture = TextureLoader.getTexture("jpg", new FileInputStream(new File("grassy.jpg")));
} catch (IOException e) {
e.printStackTrace();
}
displayID = glGenLists(1);
GL11.glNewList(displayID, GL11.GL_COMPILE);
texture.bind();
GL11.glPushMatrix();
GL11.glScalef(scale.x, scale.y, scale.z);
GL11.glBegin(GL11.GL_QUADS);
int heightmapExaggeration = 10;
for(int x=0; x < chunk_data.length; x++){
for(int y=0; y < chunk_data[x].length; y++){
GL11.glColor3f(chunk_color_data[x][y].getX(), chunk_color_data[x][y].getY(), chunk_color_data[x][y].getZ());
GL11.glTexCoord2f(0, 0);
GL11.glVertex3f(x*0.25f, getHeightAt(x, y)*heightmapExaggeration, y*0.25f);
GL11.glTexCoord2f(1, 0);
GL11.glVertex3f((x+1)*0.25f, getHeightAt(x+1, y)*heightmapExaggeration, y*0.25f);
GL11.glTexCoord2f(1, 1);
GL11.glVertex3f((x+1)*0.25f, getHeightAt(x+1, y+1)*heightmapExaggeration, (y+1)*0.25f);
GL11.glTexCoord2f(0, 1);
GL11.glVertex3f(x*0.25f, getHeightAt(x, y+1)*heightmapExaggeration, (y+1)*0.25f);
}
}
GL11.glEnd();
GL11.glPopMatrix();
texture.release();
GL11.glEndList();
}
public float getHeightAt(int x, int z){
try {
return chunk_data[x][z];
} catch(Exception e) {
return 0;
}
}
public void render() {
glPushMatrix();
glTranslatef(pos.x, pos.y, pos.z);
glCallList(displayID);
glPopMatrix();
}
public void setChunkDataAtCoords(int x, int y, float value) {
this.chunk_data[x][y] = value;
}
public float[][] getChunk_data() {
return chunk_data;
}
public Vector3f[][] getChunk_color_data() {
return chunk_color_data;
}
public Vector3f getPos() {
return pos;
}
public Vector3f getScale() {
return scale;
}
public void setChunk_data(float[][] chunk_data) {
this.chunk_data = chunk_data;
}
public void setChunk_color_data(Vector3f[][] chunk_color_data) {
this.chunk_color_data = chunk_color_data;
}
public void setChunkColorDataAtCoords(int x, int y, Vector3f color) {
chunk_color_data[x][y] = color;
}
public void setPos(Vector3f pos) {
this.pos = pos;
}
public void setScale(Vector3f scale) {
this.scale = scale;
}
public boolean isVisible() {
return visible;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
}
And vbo rendering code but that don't work properly:
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import javax.imageio.ImageIO;
import org.lwjgl.BufferUtils;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
public class Terrain {
private int width = 200;
private int height = 200;
private int verticies = (3*(2*height)*width);
private int indicies = ((height*2)*width);
private FloatBuffer vBuffer = BufferUtils.createFloatBuffer(verticies);
private IntBuffer iBuffer = BufferUtils.createIntBuffer(indicies);
private IntBuffer ib = BufferUtils.createIntBuffer(indicies);
private static float[][] data;
public Terrain() {
glPushMatrix();
glScalef(0.6f, 0.6f, 0.6f);
glTranslatef(0f, 10f, 0f);
loadHeightImage();
loadHeightVerticies();
drawHeightMap();
glPopMatrix();
}
public void loadHeightImage() {
try {
BufferedImage heightmapImage = ImageIO.read(new File("height.jpg"));
data = new float[heightmapImage.getWidth()][heightmapImage.getHeight()];
Color colour;
for (int x = 0; x < data.length; x++)
{
for (int z = 0; z < data[x].length; z++)
{
colour = new Color(heightmapImage.getRGB(x, z));
data[z][x] = colour.getRed();
}
}
} catch (IOException e){
e.printStackTrace();
}
}
public void loadHeightVerticies() {
for (int z = 0; z < this.data.length - 1; z++) {
for (int x = 0; x < this.data[z].length; x++) {
vBuffer.put(x).put(this.data[z][x]).put(z);
vBuffer.put(x).put(this.data[z + 1][x]).put(z + 1);
}
}
this.vBuffer.flip();
for (int n = 0; n < indicies; n++) {
this.iBuffer.put( n);
}
this.iBuffer.flip();
}
public void drawHeightMap() {
glGenBuffers(ib);
int vHandle = ib.get(0);
int iHandle = ib.get(1);
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, vHandle);
glBufferData(GL_ARRAY_BUFFER, vBuffer, GL_STATIC_DRAW);
glVertexPointer(3, GL_FLOAT, 0, 0L);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iHandle);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, iBuffer, GL_STATIC_DRAW);
for (int x = 0; x < 400; x++) {
glDrawElements(GL_TRIANGLE_STRIP, 400, GL_UNSIGNED_SHORT, 1600 * x);
}
glDisableClientState(GL_VERTEX_ARRAY);
ib.put(0, vHandle);
glDeleteBuffers(ib);
}
}
And one more question how can I color heightmap like in the displaylist mode ? Sorry for my English.
How many chunks are you rendering? Maybe you should look at face culling if you don't need all sides of the quads.
I keep getting a NPE when I run this very basic 2D game. It has something to do with the Key Events but I am not sure how to fix this. Can someone help me? It says the NPE is on this line if (_input.up.isPressed()) {
Here is the InputHandler Class
public class InputHandler implements KeyListener {
public InputHandler(Game game) {
game.addKeyListener(this);
}
public class Key {
private boolean pressed = false;
public void toggle(boolean isPressed) {
pressed = isPressed;
}
public boolean isPressed() {
return pressed;
}
}
// public List<Key> keys = new ArrayList<Key>();
public Key up = new Key();
public Key down = new Key();
public Key left = new Key();
public Key right = new Key();
public void keyPressed(KeyEvent e) {
toggleKey(e.getKeyCode(), true);
}
public void keyReleased(KeyEvent e) {
toggleKey(e.getKeyCode(), false);
}
public void keyTyped(KeyEvent e) {
}
public void toggleKey(int keyCode, boolean isPressed) {
if (keyCode == KeyEvent.VK_W) {
up.toggle(isPressed);
} else if (keyCode == KeyEvent.VK_S) {
down.toggle(isPressed);
} else if (keyCode == KeyEvent.VK_A) {
left.toggle(isPressed);
} else if (keyCode == KeyEvent.VK_D) {
right.toggle(isPressed);
}
}
}
here is the Player Class
public class Player extends Mob {
private InputHandler _input;
private int _speed;
private int _r = 10;
private int _x, _y;
public Player(int x, int y, int speed, InputHandler input) {
super("Player", x, y, 1);
_input = input;
_speed = speed;
_x = x;
_y = y;
}
public boolean hasCollided(int dx, int dy) {
return false;
}
public void update() {
int dx = 0;
int dy = 0;
if (_input.up.isPressed()) {
dy--;
} else if (_input.down.isPressed()) {
dy++;
} else if (_input.left.isPressed()) {
dx--;
} else if (_input.right.isPressed()) {
dx++;
}
if (dx != 0 || dy != 0) {
move(dx, dy);
isMoving = true;
} else {
isMoving = false;
}
if (_x < _r)
_x = _r;
if (_y < _r)
_y = _r;
if (_x > Game.WIDTH - _r)
_x = Game.WIDTH - _r;
if (_y > Game.HEIGHT - _r)
_y = Game.HEIGHT - _r;
}
public void render(Graphics2D g) {
g.setColor(Color.BLACK);
g.fillOval(x - _r, y - _r, 2 * _r, 2 * _r);
g.setStroke(new BasicStroke(3));
g.setColor(Color.GRAY);
g.drawOval(x - _r, y - _r, 2 * _r, 2 * _r);
g.setStroke(new BasicStroke(1));
}
}
here is the game class which creates the player
public class Game extends Canvas implements Runnable {
private static Game _instance;
private static final String TITLE = "ProjectG";
public static final int WIDTH = 960;
public static final int HEIGHT = WIDTH * 3 / 4;
private static final int SCALE = 1;
// to make it have a higher resolution double the width and height but half
// the scale. You are doubling the width and height but keeping the same
// window size by reducing the scale
public static final Dimension SIZE = new Dimension(WIDTH * SCALE, HEIGHT * SCALE);
private static final int UPDATE_RATE = 60;
private static final int RENDER_RATE = 60;
private JFrame _frame;
private Thread _thread;
private boolean _running = false;
private int _tps = 0;
private int _fps = 0;
private int _totalTicks = 0;
private BufferedImage image;
private Graphics2D g;
public InputHandler input;
private Player player;
public Game() {
_instance = this;
setPreferredSize(SIZE);
setMinimumSize(SIZE);
setMaximumSize(SIZE);
_frame = new JFrame(TITLE);
_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
_frame.setLayout(new BorderLayout());
_frame.add(_instance, BorderLayout.CENTER);
_frame.pack();
_frame.setResizable(false);
_frame.setLocationRelativeTo(null);
_frame.setVisible(true);
player = new Player(Game.WIDTH / 2, Game.HEIGHT / 2, 1, input);
}
public synchronized void start() {
_running = true;
_thread = new Thread(this, TITLE + "_main");
_thread.start();
}
public synchronized void stop() {
_running = false;
if (_thread != null) {
try {
_thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void run() {
double lastUpdateTime = System.nanoTime();
double lastRenderTime = System.nanoTime();
final int ns = 1000000000;
final double nsPerUpdate = (double) ns / UPDATE_RATE;
final double nsPerRender = (double) ns / RENDER_RATE;
final int maxUpdatesBeforeRender = 1;
int lastSecond = (int) lastUpdateTime / ns;
int tickCount = 0;
int renderCount = 0;
image = new BufferedImage(WIDTH * SCALE, HEIGHT * SCALE, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) image.getGraphics();
while (_running) {
long currTime = System.nanoTime();
int tps = 0;
while ((currTime - lastUpdateTime) > nsPerUpdate && tps < maxUpdatesBeforeRender) {
update();
tickCount++;
_totalTicks++;
tps++;
lastUpdateTime += nsPerUpdate;
}
if (currTime - lastUpdateTime > nsPerUpdate) {
lastUpdateTime = currTime - nsPerUpdate;
}
float interpolation = Math.min(1.0F, (float) ((currTime - lastUpdateTime) / nsPerUpdate));
render(interpolation);
draw();
renderCount++;
lastRenderTime = currTime;
int currSecond = (int) (lastUpdateTime / ns);
if (currSecond > lastSecond) {
_tps = tickCount;
_fps = renderCount;
tickCount = 0;
renderCount = 0;
lastSecond = currSecond;
System.out.println(_tps + " TPS " + _fps + " FPS");
}
while (currTime - lastRenderTime < nsPerRender && currTime - lastUpdateTime < nsPerUpdate) {
Thread.yield();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
currTime = System.nanoTime();
}
}
}
public void update() {
player.update();
}
public void render(float interpolation) {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
}
g.setColor(Color.WHITE);
g.fillRect(0, 0, WIDTH * SCALE, HEIGHT * SCALE);
g.setColor(Color.BLACK);
g.drawString("TPS: " + _fps + " FPS: " + _fps, 10, 20);
player.render(g);
}
public void draw() {
Graphics g2 = this.getGraphics();
g2.drawImage(image, 0, 0, null);
g2.dispose();
}
public Game getGame() {
return this;
}
}
You haven't initialized input, so what you pass to
player = new Player(Game.WIDTH / 2, Game.HEIGHT / 2, 1, input);
is null. You need to initialize it before
input = new InputHandler(this);