Effectively drawing a lot of elements on an Android canvas - java

I'm making an interactive story editor for Android. The story contains info about author, its name and an array of scenes:
public class Story {
public ArrayList<Scene> scenes;
private String author;
private String name;
public Story(){
scenes = new ArrayList<Scene>();
Scene s = new Scene(); /* Initializing a new story adds a first scene to it. */
this.add(s);
}
public void add(Scene s){ scenes.add(s); }
}
Each scene contains info about its background and an array of things (elements):
public class Scene {
private static final String DEFAULT_B = "#000000";
public ArrayList<Thing> things;
public String background;
Scene(){
things = new ArrayList<Thing>();
this.background = DEFAULT_B;
for(int i = 1; i <= 1000; i++){
Thing t = new Thing();
t.setText("Test " + i);
add(t);
}
}
public void add(Thing t){ things.add(t); }
}
Each thing is a little bit more complicated:
public class Thing {
/* constants removed */
private float w;
private float h;
private float x;
private float y;
private String background_color;
private String text_color;
private String text;
Thing(){
/* initialize with constants */
}
/* getters and setters removed */
public void onTouch(double x, double y){
Toast.makeText(MainActivity.instance, "Clicked on Thing '" + this.text + "'", Toast.LENGTH_SHORT).show();
}
public RectF box(){
return new RectF(x, y, x+w, y+h);
}
public int resizeFrom(float x, float y){ /* try resizing */
for(RectF r: getResizerRects()){
if(inflatedRect(r, 15).contains(x, y)) return getResizerRects().indexOf(r);
}
return -1;
}
public void render(Canvas canvas, boolean sel){
Paint p = new Paint();
p.setAntiAlias(true);
RectF r = box();
p.setColor(Color.parseColor(background_color)); //todo res parser
canvas.drawRect(r, p);
p.setColor(Color.parseColor(text_color));
float font_size = 30.0f;
p.setTextSize(font_size);
Rect b = new Rect();
p.getTextBounds(text, 0, text.length(), b);
canvas.drawText(text, x + 10, y + 35, p);
p.setStyle(Paint.Style.STROKE);
p.setStrokeWidth(2);
p.setColor(Color.BLACK);
canvas.drawRect(r, p);
if(sel) drawResizers(canvas);
}
private ArrayList<RectF> getResizerRects(){
ArrayList<RectF> a = new ArrayList<>();
a.add(centerRect(x, y));
a.add(centerRect(x+w/2, y));
a.add(centerRect(x+w, y));
a.add(centerRect(x, y+h/2));
a.add(centerRect(x+w, y+h/2));
a.add(centerRect(x, y+h));
a.add(centerRect(x+w/2, y+h));
a.add(centerRect(x+w, y+h));
return a;
}
private RectF inflatedRect(RectF r, float d){
return new RectF(r.left - d, r.top - d, r.right + d*2, r.bottom + d*2);
}
private void drawResizers(Canvas c){
for(RectF r: getResizerRects()) drawResizer(c, r);
}
private RectF centerRect(float x, float y){
final float size = 14.0f;
return new RectF(x - size/2, y - size/2, x+size/2, y+size/2);
}
private void drawResizer(Canvas canvas, RectF r){
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
canvas.drawRect(r, paint);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(2);
paint.setColor(Color.BLACK);
canvas.drawRect(r, paint);
}
}
This gets drawn on StoryView:
public class StoryView extends View{
private Story story;
private int scene;
private int selected_thing;
private int resize_corner;
private PointF click;
private Paint p;
private int width;
private int height;
public StoryView(Context context) {
super(context);
p = new Paint();
p.setAntiAlias(true);
this.story = null;
this.scene = 0;
this.selected_thing = -1;
this.resize_corner = -1;
this.click = new PointF();
this.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
StoryView.this.onTouch(event.getX(), event.getY(), event.getAction());
return true;
}
});
}
private void onTouch(float x, float y, int event){
Scene s = this.story.scenes.get(scene);
if(event == MotionEvent.ACTION_DOWN) {
boolean was_selected = false;
if(selected_thing != -1) resize_corner = s.things.get(selected_thing).resizeFrom(x, y);
if(resize_corner == -1) {
for (Thing t : s.things) {
if (t.box().contains(x, y)) {
t.onTouch(x, y);
was_selected = true;
selected_thing = s.things.indexOf(t);
click.x = x - t.getPosition().x;
click.y = y - t.getPosition().y;
}
}
}
if(!was_selected && resize_corner == -1) selected_thing = -1;
}
else if(event == MotionEvent.ACTION_MOVE){
if(selected_thing != -1){
if(resize_corner != -1){ // resize
if(resize_corner == 0){
RectF box = s.things.get(selected_thing).box();
box.left = x;
box.top = y;
s.things.get(selected_thing).setBox(box);
}
else if(resize_corner == 1){
RectF box = s.things.get(selected_thing).box();
box.top = y;
s.things.get(selected_thing).setBox(box);
}
else if(resize_corner == 2){
RectF box = s.things.get(selected_thing).box();
box.right = x;
box.top = y;
s.things.get(selected_thing).setBox(box);
}
else if(resize_corner == 3){
RectF box = s.things.get(selected_thing).box();
box.left = x;
s.things.get(selected_thing).setBox(box);
}
else if(resize_corner == 4){
RectF box = s.things.get(selected_thing).box();
box.right = x;
s.things.get(selected_thing).setBox(box);
}
else if(resize_corner == 5){
RectF box = s.things.get(selected_thing).box();
box.left = x;
box.bottom = y;
s.things.get(selected_thing).setBox(box);
}
else if(resize_corner == 6){
RectF box = s.things.get(selected_thing).box();
box.bottom = y;
s.things.get(selected_thing).setBox(box);
}
else if(resize_corner == 7){
RectF box = s.things.get(selected_thing).box();
box.right = x;
box.bottom = y;
s.things.get(selected_thing).setBox(box);
}
}
else s.things.get(selected_thing).setPosition(x-click.x, y-click.y); // move
}
}
else if(event == MotionEvent.ACTION_UP){
resize_corner = -1;
}
}
public void play(Story s){
this.story = s;
}
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
Scene s = this.story.scenes.get(scene);
canvas.drawColor(Color.parseColor(s.background)); // todo: add a resource parser: background can be image or color
for (Thing t: s.things){
boolean sel = s.things.indexOf(t) == selected_thing;
t.render(canvas, sel);
}
update();
}
protected void update(){
invalidate();
}
protected void onSizeChanged(int w, int h, int _w, int _h){
super.onSizeChanged(w, h, _w, _h);
width = w;
height = h;
}
}
Which gets called from MainActivity:
public class MainActivity extends AppCompatActivity {
StoryView storyView;
public static MainActivity instance;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
}
private void init(){
instance = this;
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
storyView = new StoryView(this);
setContentView(storyView);
StoryManager.deleteStory("test");
StoryManager.createStory("test");
Story test = StoryManager.loadStory("test");
storyView.play(test);
}
}
StoryManager uses Gson to load / save stories from file.
The problem is that if there's too many Things to draw (I tried drawing 1000) the app becomes a slideshow and this appears in log:
I/Choreographer: Skipped 69 frames! The application may be doing too much work on its main thread.
I/Choreographer: Skipped 33 frames! The application may be doing too much work on its main thread.
I/art: Background sticky concurrent mark sweep GC freed 54541(1701KB) AllocSpace objects, 0(0B) LOS objects, 11% free, 13MB/15MB, paused 1.346ms total 100.998ms
I/Choreographer: Skipped 251 frames! The application may be doing too much work on its main thread.
Maybe there's much more efficient way to render such stuff? I have no errors and lags if there are 100 Things.
EDIT: The Choreographer message still appears at 100 Things.

Related

Rectangle intersects not working while jumping

I am making a game with android. The player is a rectangle that has to jump over obstacles. When i jump i decrease the height and the y coordinates. When i run the game the rectangle is jumping but when i try to jump over an obstacle its still hitting it. So i think i forget to change a value but i have no idea what value. Sorry for my bad english and i am a beginner at coding.
This is my Player class:
package com.example.niek.speelveld;
import android.graphics.Canvas;
import android.graphics.Paint;
/**
* Created by Niek on 15-8-2017.
*/
public class Player extends GameObject {
private int score;
private boolean up;
private boolean playing;
private long startTime;
private int h = 0;
private boolean jump;
public Player(int x , int y){
super.x = x;
super.y = y;
width = 100;
height = GamePanel.HEIGHT;
score = 0;
startTime = System.nanoTime();
}
public void setUp(boolean b){up = b;}
public void update(){
long elapsed = (System.nanoTime()-startTime)/1000000;
if(elapsed>100){
score++;
startTime = System.nanoTime();
}
if(up && h == 0){
jump = true;
up = false;
}
if (jump) {
if (h < 120) {
h = h + 7;
height = height - 7;
y = y - 7;
} else {
jump = false;
}
} else {
if (h > 0) {
h = h - 7;
height = height + 7;
y = y + 7;
}
}
}
public void draw(Canvas canvas){
Paint myPaint = new Paint();
myPaint.setStyle(Paint.Style.STROKE);
myPaint.setStrokeWidth(7);
canvas.drawRect(x, y, width + x, height, myPaint );
myPaint.setStrokeWidth(1);
canvas.drawText("HIGHSCORE " + score, GamePanel.WIDTH - 100 , 0+myPaint.getTextSize(), myPaint);
}
public int getScore(){return score;}
public boolean getPlaying(){return playing;}
public void setPlaying(boolean b){playing = b;}
//public void resetScore(){score = 0;}
public boolean getJump() {
return jump;
}
}
And in my Gamepanel class i use these 2 methods. When i call the class obstacle.get(i).update(); its only updating the x value so its moving towards the player.
public void update(){
if(player.getPlaying()) {
bg.update();
player.update();
//Add obstacles with timer
long obstacleElapsed = (System.nanoTime()-obstacleStartTime)/1000000;
if(obstacleElapsed >(2000 - player.getScore()/4)){
obstacles.add(new Obstacle(BitmapFactory.decodeResource(getResources(), R.drawable.rsz_spike1), WIDTH + 10, HEIGHT - 51, 14, 51, player.getScore()));
//reset timer
obstacleStartTime = System.nanoTime();
}
}
//Loop through every obstacle and check collision
for(int i = 0; i<obstacles.size(); i++){
obstacles.get(i).update();
if (collision(obstacles.get(i), player)) {
obstacles.remove(i);
player.setPlaying(false);
Intent intent = new Intent(c, Result.class);
intent.putExtra("SCORE", player.getScore());
c.startActivity(intent);
break;
}
//Remove obstacles that are out of the screen
if (obstacles.get(i).getX() < -100) {
obstacles.remove(i);
break;
}
}
}
public boolean collision(GameObject o, GameObject p){
if(Rect.intersects(o.getRectangle(), p.getRectangle())){
return true;
}
return false;
}
#Override
public void draw(Canvas canvas){
//Get Width and Height from screen
final float scaleFactorX = (float)getWidth()/WIDTH;
final float scaleFactorY = (float)getHeight()/HEIGHT;
if(canvas!=null) {
final int savedState = canvas.save();
canvas.scale(scaleFactorX, scaleFactorY);
bg.draw(canvas);
player.draw(canvas);
//Draw obstacles
for(Obstacle o : obstacles ){
o.draw(canvas);
}
canvas.restoreToCount(savedState);
}
}
And finally the Player and the Obstacle class extends Gameobject where i have the getRectangle method.
public Rect getRectangle(){
return new Rect(x, y, x+width, y+height);
}

The onTouchEvent is not being called

I am making a game app that displays random circles all across the screen. This is all done in the onDraw method by making a never ending loop. However in the onTouchEvent method there is code that is called when a circle is clicked. The problem is when a circle is "touched" nothing happens, but sometimes something does(if you click it a lot before it disappears). Id like to know if there is a way to get the onTouch method working so these circles can be clicked.
public class DrawingView extends View{
public DrawingView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
RectF rectf = new RectF(0, 0, 200, 0);
private static final int w = 100;
public static int lastColor = Color.BLACK;
private final Random random = new Random();
private final Paint paint = new Paint();
private final int radius = 230;
private final Handler handler = new Handler();
public static int redColor = Color.RED;
public static int greenColor = Color.GREEN;
int randomWidth = 0;
int randomHeight = 0;
public static int addPoints = 0;
public static int savedScore;
public static List<String> a = new ArrayList<String>();
public static String[] savedScores = new String[a.size()];
Paint red;
public static int howManyPoints;
public static int highestScore = 0;
boolean isTouched;
Thread newThread = new Thread();
int t = 1;
int l = 0;
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
//handler.post(updateCircle);
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
// handler.removeCallbacks(updateCircle);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// your other stuff here
Paint back = new Paint();
back.setColor(Color.BLACK);
Rect background = new Rect();
background.set(0, 0, canvas.getWidth(),canvas.getHeight() );
canvas.drawRect(background, back);
Paint newPaint = new Paint();
newPaint.setColor(Color.BLUE);
newPaint.setTextSize(60);
canvas.drawText("Beta v2", 10, 60, newPaint);
if(l < t){
lastColor = random.nextInt(2) == 1 ? redColor : greenColor;
paint.setColor(lastColor);
if(random == null){
randomWidth =(int) (random.nextInt(Math.abs(getWidth()-radius/2)) + radius/2f);
randomHeight = (random.nextInt((int)Math.abs((getHeight()-radius/2 + radius/2f))));
}else {
randomWidth =(int) (random.nextInt(Math.abs(getWidth()-radius/2)) + radius/2f);
randomHeight = (random.nextInt((int)Math.abs((getHeight()-radius/2 + radius/2f))));
}
canvas.drawCircle(randomWidth , randomHeight , radius , paint);
try {
newThread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
invalidate();
}
red = new Paint();
red.setColor(Color.BLUE);
red.setTextSize(150);
canvas.drawText("" + addPoints, 500, 1350, red);
}
#SuppressWarnings("deprecation")
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
int x = (int) event.getX();
int y = (int) event.getY();
if(isInsideCircle(x, y) == true){
if(lastColor == redColor){
howManyPoints = addPoints;
if(howManyPoints > highestScore){
highestScore = howManyPoints;
}
//handler.removeCallbacks(updateCircle);
lastColor = redColor;
addPoints = 0;
Intent i = new Intent(this.getContext(), YouFailed.class);
this.getContext().startActivity(i);
l = 1;
}
if(lastColor == greenColor){
addPoints++;
isTouched = true;
l = 0;
}
}else {
}
}
return false;
}
public boolean isInsideCircle(int x, int y){
if ((((x - randomWidth)*(x - randomWidth)) + ((y - randomHeight)*(y - randomHeight))) < ((radius)*(radius))){
return true;
}
return false;
}
}
You forgot to return true when you touch down
Try to add this
if(event.getAction() == MotionEvent.ACTION_DOWN){
//your code
return true;
}

How to test if something has not been touched after a circle has been drawn

I have an app that draws random circles to the screen one after another. These circles colors are also random either green or red. If you are to click a red one you loose the game if you are to click a green one you get points. What I am trying to do is add a boolean that checks if someone has not clicked on a green circle or has not clicked the screen at all when a green circle is displayed. If a red circle is displayed and the user does not click anywhere nothing happens, but in the event that a green circle is displayed and nothing is clicked the user should be redirected to another class and loose all of there points. I have tried to make a boolean called isTouched and gave it the value false then placed it all throughout my code but nothing seems to work. Here is my code if the isTouched boolean is to equal false.
if(isTouched == false){
howManyPoints = addPoints;
handler.removeCallbacks(updateCircle);
lastColor = redColor;
addPoints = 0;
Intent i = new Intent(this.getContext(), YouFailed.class);
this.getContext().startActivity(i);
}
and here is the entire class.
public class DrawingView extends View{
public DrawingView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
RectF rectf = new RectF(0, 0, 200, 0);
private static final int w = 100;
public static int lastColor = Color.BLACK;
private final Random random = new Random();
private final Paint paint = new Paint();
private final int radius = 230;
private final Handler handler = new Handler();
public static int redColor = Color.RED;
public static int greenColor = Color.GREEN;
int randomWidth = 0;
int randomHeight = 0;
public static int addPoints = 0;
public static int savedScore;
public static List<String> a = new ArrayList<String>();
public static String[] savedScores = new String[a.size()];
Paint red;
public static int howManyPoints;
boolean isTouched;
private final Runnable updateCircle = new Runnable() {
#Override
public void run() {
lastColor = random.nextInt(2) == 1 ? redColor : greenColor;
paint.setColor(lastColor);
if(addPoints < 10){
handler.postDelayed(this, 700);
}
if(addPoints > 9 && addPoints < 30){
handler.postDelayed(this,550);
}
if(addPoints > 29){
handler.postDelayed(this, 450);
}
postInvalidate();
}
};
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
handler.post(updateCircle);
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
handler.removeCallbacks(updateCircle);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// your other stuff here
Paint back = new Paint();
back.setColor(Color.BLACK);
Rect background = new Rect();
background.set(0, 0, canvas.getWidth(),canvas.getHeight() );
canvas.drawRect(background, back);
Paint newPaint = new Paint();
newPaint.setColor(Color.BLUE);
newPaint.setTextSize(60);
canvas.drawText("ALPHA 1.64.5", 10, 60, newPaint);
if(random == null){
randomWidth =(int) (random.nextInt(Math.abs(getWidth()-radius/2)) + radius/2f);
randomHeight = (random.nextInt((int)Math.abs((getHeight()-radius/2 + radius/2f))));
}else {
randomWidth =(int) (random.nextInt(Math.abs(getWidth()-radius/2)) + radius/2f);
randomHeight = (random.nextInt((int)Math.abs((getHeight()-radius/2 + radius/2f))));
}
canvas.drawCircle(randomWidth, randomHeight, radius, paint);
red = new Paint();
red.setColor(Color.BLUE);
red.setTextSize(150);
canvas.drawText("" + addPoints, 500, 1350, red);
}
#SuppressWarnings("deprecation")
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
int x = (int) event.getX();
int y = (int) event.getY();
if(isInsideCircle(x, y) == true){
//Do your things here
if(lastColor == redColor){
//saveScore();
howManyPoints = addPoints;
handler.removeCallbacks(updateCircle);
lastColor = redColor;
addPoints = 0;
Intent i = new Intent(this.getContext(), YouFailed.class);
this.getContext().startActivity(i);
}
if(lastColor == greenColor){
addPoints++;
isTouched = true;
}
}else {
}
}
if(isTouched == false){
howManyPoints = addPoints;
handler.removeCallbacks(updateCircle);
lastColor = redColor;
addPoints = 0;
Intent i = new Intent(this.getContext(), YouFailed.class);
this.getContext().startActivity(i);
}
return false;
}
public void saveScore() {
a.add("" + addPoints);
//if(Integer.parseInt(savedScores[1]) < addPoints){
//savedScores[2] = savedScores[1];
//int x = Integer.parseInt(savedScores[1]);
//x = addPoints;
//}
}
public boolean isInsideCircle(int x, int y){
if ((((x - randomWidth)*(x - randomWidth)) + ((y - randomHeight)*(y - randomHeight))) < ((radius)*(radius))){
return true;
}
return false;
}
}

Creating draggable and resizable Component in Java

How to create a component that can be dragged and resized in Java Swing?
Like "Text Tools" text box feature in MS Paint, highlighted by red border in image.
I only want drag and resize feature, not text formatting.
How can I implement this component using Java Swing?
In my quest to solve this problem, I found Piccolo2d ZUI library.
That's exactly, what I was looking for! However, it might not be best approach just to implement a "Draggable & Resizable Text Box", but I got it working in under an hour using Piccolo2d. So, I am posting the code here, if someone can find it useful.
Here is the screenshot of sample application!
I tried to make the code as describable as possible, so it's a bit long.
You'll require piccolo2d-core-XXX.jar & piccolo2d-extras-XXX.jar to run this code, that can be downloaded from Maven Central Repository. I used version 3.0 & didn't tested with any other version!
Custom Component Class
class PBox extends PNode {
private PCanvas canvas;
private Rectangle2D rectangle;
private Cursor moveCursor;
public PBox(PCanvas canvas) {
this(0, 0, 50, 50, canvas);
}
public PBox(double x, double y, double width, double height, PCanvas canvas) {
this.canvas = canvas;
rectangle = new Rectangle2D.Double();
moveCursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
addAnchors(x, y, width, height);
setBounds(x, y, width, height);
setInputEventListener();
}
private void addAnchors(double x, double y, double width, double height) {
addChild(new Anchor(SwingConstants.NORTH));
addChild(new Anchor(SwingConstants.NORTH_EAST));
addChild(new Anchor(SwingConstants.EAST));
addChild(new Anchor(SwingConstants.SOUTH_EAST));
addChild(new Anchor(SwingConstants.SOUTH));
addChild(new Anchor(SwingConstants.SOUTH_WEST));
addChild(new Anchor(SwingConstants.WEST));
addChild(new Anchor(SwingConstants.NORTH_WEST));
}
private void setInputEventListener() {
addInputEventListener(new PBasicInputEventHandler() {
#Override
public void mouseEntered(PInputEvent event) {
canvas.setCursor(moveCursor);
}
#Override
public void mouseExited(PInputEvent event) {
canvas.setCursor(Cursor.getDefaultCursor());
}
#Override
public void mouseDragged(PInputEvent event) {
PDimension delta = event.getDeltaRelativeTo(PBox.this);
translate(delta.width, delta.height);
event.setHandled(true);
}
});
}
#Override
protected void layoutChildren() {
Iterator iterator = getChildrenIterator();
int position = SwingConstants.NORTH;
while (iterator.hasNext()) {
PNode anchor = (PNode) iterator.next();
anchor.setBounds(getAnchorBounds(position));
++position;
}
}
private Rectangle2D getAnchorBounds(int position) {
double x = 0, y = 0;
Rectangle2D b = getBounds();
switch (position) {
case SwingConstants.NORTH:
x = b.getX()+b.getWidth()/2;
y = b.getY();
break;
case SwingConstants.NORTH_EAST:
x = b.getX()+b.getWidth();
y = b.getY();
break;
case SwingConstants.EAST:
x = b.getX()+b.getWidth();
y = b.getY()+b.getHeight()/2;
break;
case SwingConstants.SOUTH_EAST:
x = b.getX()+b.getWidth();
y = b.getY()+b.getHeight();
break;
case SwingConstants.SOUTH:
x = b.getX()+b.getWidth()/2;
y = b.getY()+b.getHeight();
break;
case SwingConstants.SOUTH_WEST:
x = b.getX();
y = b.getY()+b.getHeight();
break;
case SwingConstants.WEST:
x = b.getX();
y = b.getY()+b.getHeight()/2;
break;
case SwingConstants.NORTH_WEST:
x = b.getX();
y = b.getY();
break;
}
return new Rectangle2D.Double(x-2, y-2, 4, 4);
}
#Override
public boolean setBounds(double x, double y, double width, double height) {
if (super.setBounds(x, y, width, height)) {
rectangle.setFrame(x, y, width, height);
return true;
}
return false;
}
#Override
public boolean intersects(Rectangle2D localBounds) {
return rectangle.intersects(localBounds);
}
#Override
protected void paint(PPaintContext paintContext) {
Graphics2D g2 = paintContext.getGraphics();
g2.setPaint(Color.BLACK);
g2.setStroke(new BasicStroke(1.0f,
BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER,
1.0f, new float[]{4.0f}, 0));
g2.draw(rectangle);
}
class Anchor extends PNode {
private Rectangle2D point;
private Cursor resizeCursor;
Anchor(int position) {
point = new Rectangle2D.Double();
setCursor(position);
setInputEventListener(position);
}
private void setCursor(int position) {
switch (position) {
case SwingConstants.NORTH:
resizeCursor = Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR);
break;
case SwingConstants.NORTH_EAST:
resizeCursor = Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR);
break;
case SwingConstants.EAST:
resizeCursor = Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR);
break;
case SwingConstants.SOUTH_EAST:
resizeCursor = Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR);
break;
case SwingConstants.SOUTH:
resizeCursor = Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR);
break;
case SwingConstants.SOUTH_WEST:
resizeCursor = Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR);
break;
case SwingConstants.WEST:
resizeCursor = Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR);
break;
case SwingConstants.NORTH_WEST:
resizeCursor = Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR);
break;
default:
resizeCursor = Cursor.getDefaultCursor();
}
}
private void setInputEventListener(final int position) {
addInputEventListener(new PBasicInputEventHandler() {
#Override
public void mouseEntered(PInputEvent event) {
canvas.setCursor(resizeCursor);
event.setHandled(true);
}
#Override
public void mouseExited(PInputEvent event) {
canvas.setCursor(Cursor.getDefaultCursor());
event.setHandled(true);
}
#Override
public void mouseDragged(PInputEvent event) {
PDimension delta = event.getDeltaRelativeTo(Anchor.this);
PNode parent = getParent();
if (position == SwingConstants.EAST
|| position == SwingConstants.NORTH_EAST
|| position == SwingConstants.SOUTH_EAST) {
parent.setWidth(parent.getWidth() + delta.width);
} else if (position == SwingConstants.WEST
|| position == SwingConstants.NORTH_WEST
|| position == SwingConstants.SOUTH_WEST) {
parent.setX(parent.getX() + delta.width);
parent.setWidth(parent.getWidth() - delta.width);
}
if (position == SwingConstants.SOUTH
|| position == SwingConstants.SOUTH_EAST
|| position == SwingConstants.SOUTH_WEST) {
parent.setHeight(parent.getHeight() + delta.height);
} else if (position == SwingConstants.NORTH
|| position == SwingConstants.NORTH_EAST
|| position == SwingConstants.NORTH_WEST) {
parent.setY(parent.getY() + delta.height);
parent.setHeight(parent.getHeight() - delta.height);
}
event.setHandled(true);
}
});
}
#Override
public boolean setBounds(double x, double y, double width, double height) {
if (super.setBounds(x, y, width, height)) {
point.setFrame(x, y, width, height);
return true;
}
return false;
}
#Override
public boolean intersects(Rectangle2D localBounds) {
return point.intersects(localBounds);
}
#Override
protected void paint(PPaintContext paintContext) {
Graphics2D g2 = paintContext.getGraphics();
g2.setColor(Color.WHITE);
g2.fill(point);
g2.setStroke(new BasicStroke(1.0f));
g2.setColor(Color.BLACK);
g2.draw(point);
}
}
}
And, the main class
public class Piccolo2DExample extends PFrame {
#Override
public void initialize() {
PCanvas canvas = getCanvas();
PNode text = new PText("Draggable & Resizable Box using Piccolo2d");
text.scale(2.0);
canvas.getCamera().addChild(text);
PLayer layer = canvas.getLayer();
PNode aLayerNode = new PText("A_Layer_Node");
aLayerNode.setOffset(10, 50);
layer.addChild(aLayerNode);
// Adding the component to layer
layer.addChild(new PBox(50, 100, 250, 50, canvas));
}
public static void main(String[] args) {
PFrame frame = new Piccolo2DExample();
frame.setSize(800, 640);
}
}

Integer will call to one class, but not to another?

I'm trying to make the game "Snake," but I'm getting stuck on the tail. Right
now, I'm just trying to make the first tail block have the same coordinates as the
head. Here's what I have. For the main class:
public class Game extends JPanel implements ActionListener {
Snake p;
RandomDot r;
Trail trail;
Point w;
Image img;
Timer time;
int t=75;
int score = 0;
int count = 0;
int x, y;
boolean lost = false;
public Game(){
p = new Snake();
r = new RandomDot();
trail = new Trail();
w = new Point();
addKeyListener(new AL());
setFocusable(true);
ImageIcon i = new ImageIcon("C:/Matt's stuff/background.png");
img = i.getImage();
time = new Timer(t, this);
time.start();
}
#Override
public void actionPerformed(ActionEvent e)
{
p.move();
p.moveup();
w.points();
trail.getFirstDot();
trail.findCoords();
if (score>=1)
{
trail.getFirstDot();
}
if (lost==true)
{
score++;
r.getRandom();
lost = false;
}
repaint();
checkCollisions();
}
public int score()
{
return score;
}
public boolean getLost()
{
return lost;
}
public void checkCollisions()
{
Rectangle r1 = r.getBounds();
Rectangle r2 = p.getBounds();
if (r1.intersects(r2))
{
lost = true;
}
}
#Override
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(img, 0, 0, null);
g2d.drawImage(p.getImage(), p.getX(), p.getY(), null);
g2d.drawImage(r.getImage2(), r.getX2(), r.getY2(), null);
if (score>=1)
{
g2d.drawImage(trail.getImage(), trail.getX(), trail.getY(), null);
}
System.out.println(score + "00");
}
private class AL extends KeyAdapter{
#Override
public void keyReleased(KeyEvent e)
{
p.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e)
{
p.keyPressed(e);
}
}
}
For the Snake's head's class:
public class Snake {
Integer x = 480, y = 280, dx = 0, dy = 0, h, m;
boolean dead = false;
boolean didmove = false;
Image still;
RandomDot r;
Game g;
Trail t;
public Snake(){
ImageIcon i = new ImageIcon("C:/Matt's Stuff/snake.png");
still = i.getImage();
}
public Rectangle getBounds(){
return new Rectangle(x,y, 10, 10);
}
public void move(){
x = x + dx;
h = x;
didmove = true;
if (x>=990||x<=5){
dead = true;
x = 480;
y = 280;
dx = 0;
dy = 0;
didmove = false;
}
}
public void moveup(){
y = y + dy;
m = y;
didmove = true;
if (y>=590||y<=0){
dead = true;
x = 480;
y = 280;
dx = 0;
dy = 0;
didmove = false;
}
}
public Integer getX(){
return x;
}
public Integer getY(){
return y;
}
public Image getImage(){
return still;
}
public boolean getBoolean(){
return dead;
}
public boolean didmove(){
return didmove;
}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT){
if (dead == false){
dx = -10;
dy = 0;
} else {
x = 480;
y = 280;
dx = 0;
dy = 0;
}
}
if (key == KeyEvent.VK_RIGHT){
if (dead == false){
dx = 10;
dy = 0;
} else {
x = 480;
y = 280;
dx = 0;
dy = 0;
}
}
if (key == KeyEvent.VK_UP){
if (dead == false){
dy = -10;
dx = 0;
}else {
x = 480;
y = 280;
dx = 0;
dy = 0;
}
}
if (key == KeyEvent.VK_DOWN){
if (dead == false){
dy = 10;
dx = 0;
}else {
x = 480;
y = 280;
dx = 0;
dy = 0;
}
}
}
public void keyReleased(KeyEvent e){
int key = e.getKeyCode();
}
}
And lastly, the tail:
public class Trail {
Image still;
Integer x = 500, y = 500, dx, dy, dx2, dy2;
Game g;
Snake p;
Point d;
int count=0;
boolean visible = false;
public Trail(){
ImageIcon i = new ImageIcon("C:/Matt's Stuff/Dot.png");
still = i.getImage();
p = new Snake();
d = new Point();
}
public void getFirstDot(){
visible = true;
}
public void findCoords(){
if (visible == true)
{
x = p.getX();
y = p.getY();
}
}
public Integer getX(){
return x;
}
public Integer getY(){
return y;
}
public Image getImage(){
return still;
}
}
Now my problem is this: The p.getX() and p.getY() in the tail class do not work! The tail block just sits there where the snake's head initially started! I don't know what is going on, none of my research seems to help! Please help me out? Why is it that p.getX() and p.getY() will work in the main Game class, but not the Tail's? Thank you in advance!
You're creating a new Snake() inside your Trail constructor, and then referring to that Snake instead of the one the Game knows about. Instead of creating a new Snake, you should pass in a reference to the constructor, so that you call the methods of the object that is actually being updated:
// In the Trail class
public Trail(Snake s) {
p = s;
// other stuff
}
// In the Game class:
trail = new Trail(p);
// ...
Now when you call p.getX() and so on, you'll actually be pointing at the correct Snake, so you should see your position update correctly.
You should pass the reference of existing Snake object to Trail constructor to make it work. For example in Game class your code should be like this:
public Game(){
p = new Snake();
r = new RandomDot();
trail = new Trail(p);//Pass the reference of Snake so that you get all information w.r.t the current Snake in consideration
w = new Point();
addKeyListener(new AL());
setFocusable(true);
ImageIcon i = new ImageIcon("C:/Matt's stuff/background.png");
img = i.getImage();
time = new Timer(t, this);
time.start();
}
And change the Trail constructor as follows:
public Trail(Snake p){
ImageIcon i = new ImageIcon("C:/Matt's Stuff/Dot.png");
still = i.getImage();
this.p = p;
d = new Point();
}

Categories