I have problem with animation in android.
My animations working good only on 1080x1920 480dpi display. But i don't know how made app for any display.
If I use method from http://www.i-programmer.info/programming/android/8797-android-adventures-beginning-bitmap-graphics.html?start=4 Animations run, ok but made shadows, so no rewrite display if I write on display something I not delete thise from display.
If I use method. Main activity have one threat
public class UpdateThread implements Runnable {
#Override
public void run() {
while(bez){
try {
myThread.sleep(50);
} catch (Exception ex) {}
MainActivity.this.updateHandler.sendEmptyMessage(0);
}
}
and Class Game who every 50ms do
public void update() {
x += 1;
y += 2;
}
And on draw method in this class
protected void onDraw(Canvas canvas) {
Plocha pozadie = new Plocha(paint, canvas, X0, Y0, vzdialenost);
if (nehra==true) {
paint.setStrokeWidth(13F);
paint.setStyle(Paint.Style.STROKE);
LevelUp(level);
paint.setTypeface(Typeface.DEFAULT_BOLD);
paint.setStyle(Paint.Style.FILL);
pozadie.vypis(paint, canvas, "Score", 100, 100, 6);
pozadie.vypis(paint, canvas, Integer.toString(zasah), 90, 200, 9);
pozadie.vypis(paint, canvas, "Level", 850, 100, 6);
pozadie.vypis(paint, canvas, Integer.toString(level), 850, 200, 8);
pozadie.vypis(paint, canvas, "Clicks", 1080 / 2 - 100, 100, 7);
pozadie.vypis(paint, canvas, Integer.toString(click), 1080 / 2, 200, 9);
}
everything be okay (y) but only one type display.
If use
Bitmap b = Bitmap.createBitmap(1080,
1920,Bitmap.Config.ARGB_8888);
this.canvas = new Canvas(b);
this.canvas.drawColor(Color.WHITE);
this.b=b;
and rewrite some parts of code
application result is these canvas
protected void onDraw( Canvas canvas ) {
I don't know why...
ImageView im=(ImageView)findViewById(R.id.imageView222);
game = new Game(this,im);
setContentView(game);
I think so If I save setContentView(game); to imageview. will be everything okay. But I try and every ideas finish more errors.
I'm sad from...
Thanks from some ideas.
Related
I am currently working on a data visualization which takes information from a movie, that plays in realtime and creates simultaneously.
For that I want to have two seperate sketch windows. One window should show the movie playing in realtime and the other the ongoing visualization.
I can't seem to figure out how to easily add another sketch window and tried out some examples which are not working in Processing 3 anymore.
(sojamos library Control p5 for example)
Then I stumbled upon this example:
https://gist.github.com/atduskgreg/666e46c8408e2a33b09a
Eventhough I can get it to display two sketch windows at a time, I obviously cannot use the data from one window on the other one.
Is there another way to do this?
Thank you!
Nothing prevents you from declaring a function in the PWindow class (which creates a second window) which takes arguments you could use inside and call it from the other sketch.
So you can pass data in form as function arguments to the second window.
This small example passes the relative mousePressed position from the first window to the second via a function (here called evokedFromPrimary) and stores it in an ArrayList which draws them in the second window:
PWindow win;
public void settings() {
size(320, 240);
}
void setup() {
win = new PWindow();
}
void draw() {
background(255, 0, 0);
text("Click in this window to draw at a relative position in the other window", 10, 10, this.width - 20, 100);
}
void mousePressed() {
println("mousePressed in primary window");
float relPosX = map(mouseX, 0, this.width, 0, 100);
float relPosY = map(mouseY, 0, this.height, 0, 100);
win.evokedFromPrimary(relPosX, relPosY);
}
class PWindow extends PApplet {
ArrayList<PVector> vectors = new ArrayList<PVector>();
PWindow() {
super();
PApplet.runSketch(new String[] {this.getClass().getSimpleName()}, this);
}
void evokedFromPrimary(float relPosX, float relPosY) {
println("evoked from primary");
float xPos = map(relPosX, 0, 100, 0, this.width);
float yPos = map(relPosY, 0, 100, 0, this.height);
vectors.add(new PVector(xPos, yPos));
}
void settings() {
size(500, 200);
}
void setup() {
background(150);
}
void draw() {
background(150);
//store the vector size before using to avoid ConcurrentModificationException
int listLength = vectors.size();
for(int i = 0; i < listLength; i++) {
PVector v = vectors.get(i);
ellipse(v.x, v.y, random(50), random(50));
}
}
void mousePressed() {
println("mousePressed in secondary window");
}
}
The Pwindow code here is in the same .pda file.
I need some help understanding the fundamentals of scrolling over items that are drawn to a canvas in Android. Suppose I want to create a timeline where time at 0 is the top of a visualization and as time increased the timeline continues to be rendered below the previous point. If I wish to render this on Android I know I could simply create a bunch of items on a canvas by overriding onDraw(). However, let's suppose the visualization is bigger than the screen allows.
For example in the first picture below the large black box contains the entire canvas as I render it. I create a blue line that runs vertically up and down as well as several yellow, green and blue rectangles. The red box represents the screen of the Android that is rendering the visualization. As it initially opens all items are drawn but only the items contained within the red box show up on the screen.
Now if the user is to scroll down, items that initially appeared below the red box are in view while items that have gone out of the confines of the red box are no longer visable, as represented in the second picture.
I believe I need to use scrollables but I'm quite lost how to do so. I've read over this page http://developer.android.com/training/custom-views/custom-drawing.html explaining how to create your own customer images and this page http://developer.android.com/training/custom-views/making-interactive.html explaining how to make the UI interactive, but I think I'm missing something.
A sample code that illustrates this problem (this is basic, assume there is logic dictating WHERE the boxes/lines go, etc.) is as follows:
package com.example.scrolltest;
import com.example.scrolltest.Draw;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Color;
public class MainActivity extends Activity {
Draw draw;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
draw = new Draw(this);
draw.setBackgroundColor(Color.WHITE);
setContentView(draw);
}
}
and
package com.example.scrolltest;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
public class Draw extends View {
Paint paint = new Paint();
public Draw(Context context) {
super(context);
}
#Override
public void onDraw(Canvas canvas) {
paint.setColor(Color.GREEN);
canvas.drawRect(30, 30, 90, 200, paint);
paint.setColor(Color.BLUE);
canvas.drawLine(100, 20, 100, 1900, paint);
paint.setColor(Color.GREEN);
canvas.drawRect(200, 2000, 400, 3000, paint);
}
}
What I cannot figure out though, is how I use a scrollable to scroll down to the rectangles that are off of the screen. I'm also unsure if I started this correctly or should use drawables instead...
Simple Method (If the height required is not very large).
Use a ScrollView and add your Draw view in it. Compute the required height for that view in onMeasure.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
draw = new Draw(this);
draw.setBackgroundColor(Color.WHITE);
ScrollView scrollView = new ScrollView(this);
scrollView.addView(draw);
setContentView(scrollView);
}
public class Draw extends View {
Paint paint = new Paint();
public Draw(Context context) {
super(context);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Compute the height required to render the view
// Assume Width will always be MATCH_PARENT.
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = 3000 + 50; // Since 3000 is bottom of last Rect to be drawn added and 50 for padding.
setMeasuredDimension(width, height);
}
#Override
public void onDraw(Canvas canvas) {
paint.setColor(Color.GREEN);
canvas.drawRect(30, 30, 90, 200, paint);
paint.setColor(Color.BLUE);
canvas.drawLine(100, 20, 100, 1900, paint);
paint.setColor(Color.GREEN);
canvas.drawRect(200, 2000, 400, 3000, paint);
}
}
An alternative can be to use offset X/Y values.
How you handle the offset values is up to you, all though I prefer using a class I call Camera. The access should be static.
public void render(Canvas c){
c.drawRect(100 - offsetX, 100 - offsetY, 120 - offsetX, 120 - offsetY, Paints.BLUE);
}
And to pan the canvas:
float x, y;
#Override
public boolean onTouchEvent(MotionEvent ev) {
if(ev.getAction() == MotionEvent.ACTION_DOWN){
x = ev.getX();
y = ev.getY();
}else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
float currX = ev.getX();
float currY = ev.getY();
float newOffsetX = (x - currX),
newOffsetY = (y - currY);
//The next two if-statements are to add sensitivity to the scrolling.
//You can drop these if you don't plan on having touch events
//with pressing. Pressing works without this as well, but the canvas may move slightly
//I use DP to handle different screen sizes but it can be replaced with pixels. c is a context-instance
if (newOffsetY < Maths.convertDpToPixel(2, c) && newOffsetY > -Maths.convertDpToPixel(2, c))
newOffsetY = 0;
if (newOffsetX < Maths.convertDpToPixel(2, c) && newOffsetX > -Maths.convertDpToPixel(2, c))
newOffsetX = 0;
offsetX += newOffsetX;
offsetY += newOffsetY;
x = ev.getX();
y = ev.getY();
}
return true;
}
And a sample Camera-class:
public class Camera{
public static float offsetX, offsetY;
//The constructor. ix and iy is the initial offset. Useful if you are creating a game and need to change the initial offset to center around a starting position.
//Most of the time it will be enough to set the values to 0
public Camera(float ix, float iy){
this.offsetX = ix;
this.offsetY = iy;
}
}
I have a canvas drawing, I am going to use onTouch to change the colour of the drawing. It is a house, and on touching the screen once it will change to a darker shade. I have only been told that I will need to move the method calls into dayTime and nightTime, switchable by boolean, and that the text daytime and night time has to be rendered on the image accordingly.
Below is the code I used to draw the image. Any help on how to finish this would be appreciated:
/*
* DrawView.java
*/
public class DrawView extends View implements OnTouchListener
{
private Paint backgroundPaint = new Paint();
private Paint drawPaint_grass = new Paint();
private Paint drawPaint_door = new Paint();
private Paint drawPaint_house = new Paint();
private Paint drawPaint_roof = new Paint();
private Paint circlePaint = new Paint();
private Paint circlePaint_sun = new Paint();
private Paint textPaint = new Paint();
private Paint path = new Paint();
private Path trianglePath;
private float sx, sy;
public DrawView(Context context)
{
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
backgroundPaint.setColor(Color.rgb(135,250,205));
backgroundPaint.setAntiAlias(true);
backgroundPaint.setStyle(Style.FILL);
drawPaint_grass.setColor(Color.rgb(124, 252, 0));
drawPaint_grass.setStyle(Style.FILL);
drawPaint_door.setColor(Color.RED);
drawPaint_door.setStyle(Style.FILL);
//drawPaint_.setColor(Color.RED);
//drawPaint_door.setStyle(Style.FILL);
drawPaint_house.setColor(Color.rgb(205, 133, 63));
drawPaint_house.setStyle(Style.FILL);
drawPaint_roof.setColor(Color.rgb(160, 82, 45));
drawPaint_roof.setStyle(Style.FILL);
circlePaint_sun.setColor(Color.rgb(255, 255, 0));
circlePaint_sun.setStyle(Style.FILL);
trianglePath = new Path();
trianglePath.moveTo(70, 300); // starting point
trianglePath.lineTo(170,250); // 1st vertix
trianglePath.lineTo(270, 300); // 2nd vertix
trianglePath.lineTo(70, 300); // 3rd vertix and close
//path.moveTo(getRight()/2, getLeft()/2, getTop()/2, getBottom()/2);
textPaint.setColor(Color.BLACK);
textPaint.setStyle(Style.FILL);
//255, 255, 240
circlePaint.setColor(Color.rgb(211, 211, 211));
circlePaint.setStyle(Style.FILL);
this.setOnTouchListener(this);
}
#Override
public void onDraw(Canvas canvas)
{
//canvas.drawPath(path, paint);
//canvas.drawPath(path, paint);
// Draw white background
canvas.drawRect(this.getLeft(), this.getTop(), this.getRight(), this.getBottom(), backgroundPaint);
//draw a rectangle with blue paint
canvas.drawRect(0,400, 540,600, drawPaint_grass);
canvas.drawRect(100,400, 240,300, drawPaint_house);
canvas.drawRect(150,400, 190,335, drawPaint_door);
canvas.drawPath(trianglePath, drawPaint_roof);
//draw text with green paint
canvas.drawText("Muhibur Rahim", 232, 565, textPaint);
//draw a circle with red paint with the touch coordinates
canvas.drawCircle(sx-30,sy-30, 3, circlePaint);
canvas.drawCircle(80, 80, 30, circlePaint_sun);
}
public boolean onTouch(View v, MotionEvent event)
{
//update the coordinates for the OnDraw method above, with wherever we touch
sx = event.getX();
sy = event.getY();
invalidate();
return true;
}
}
I was thinking of putting the colouring part of code (circlePaint_sun.setColor(Color.rgb(255, 255, 0)) into methods (eg. static void dayTime() under private Drawview(Context, Context), and then assigning the two methods values 0 and 1, and on touch or click (i think onclick would be better) a counter increases and the values alternate between 0 and 1. However I am not sure how to use that in a code after repeated tries, any help is appreciated...
Add a private boolean dark = false; to your variables.
In your onDraw method, add something like
if (dark) backgroundPaint.setColor(Color.rgb(0,0,0));
else backgroundPaint.setColor(Color.rgb(255,255,255));
before you draw your background.
Change your boolean inside the onTouch method:
if (event.getAction() == MotionEvent.ACTION_DOWN) {
dark = !dark;
DrawView();
}
How do I find the coordinates of the screen? I know e.g. a phone would have say a 960 x 540 resolution, but in the emulators some of the edges are not filled if I draw a shape to that resolution. Is there a way around this?
For the colour of the rectangle, it is seen there are two rectangles, and two of them have the same colour despite giving two separate colours for drawPaint. Just setting a new variable e.g. drawPaint2 returns errors. How to change the colour of both?
How to use the path function in the canvas. E.g. to draw a triangle? I have included my attempt in the code but it doesn't display a triangle.
public class DrawView extends View implements OnTouchListener
{
private Paint backgroundPaint = new Paint();
private Paint drawPaint = new Paint();
private Paint circlePaint = new Paint();
private Paint textPaint = new Paint();
private Paint path = new Paint();
private float sx, sy;
public DrawView(Context context)
{
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
backgroundPaint.setColor(Color.CYAN);
backgroundPaint.setAntiAlias(true);
backgroundPaint.setStyle(Style.FILL);
drawPaint.setColor(Color.WHITE);
drawPaint.setStyle(Style.FILL);
circlePaint.setColor(Color.DKGRAY);
circlePaint.setStyle(Style.FILL);
textPaint.setColor(Color.WHITE);
textPaint.setStyle(Style.FILL);
drawPaint.setColor(Color.GREEN);
drawPaint.setStyle(Style.FILL);
circlePaint.setColor(Color.RED);
circlePaint.setStyle(Style.FILL);
path.setColor(android.graphics.Color.RED);
path.setStyle(Paint.Style.FILL);
Path path = new Path();
path.moveTo(1, 1);
path.lineTo(20, 50);
path.moveTo(20, 50);
path.lineTo(100, 100);
path.moveTo(100, 100);
path.lineTo(1, 1);
path.close();
this.setOnTouchListener(this);
}
#Override
public void onDraw(Canvas canvas)
{
//canvas.drawPath(path, paint); <-- error
// to draw background
canvas.drawRect(this.getLeft(), this.getTop(), this.getRight(), this.getBottom(), backgroundPaint);
//to draw two rectangle with blue and green paint
canvas.drawRect(100,100, 340,540, drawPaint);
canvas.drawRect(00,00, 120,80, drawPaint);
//draw text with paint
canvas.drawText("Hello Dear Leader!", 110, 160, textPaint);
//draw a circle with green paint with the touch coordinates
canvas.drawCircle(sx-30,sy-30, 30, circlePaint);
//draw a circle with red paint with the touch coordinates
canvas.drawCircle(sx-80, sy-80, 10, circlePaint);
}
public boolean onTouch(View v, MotionEvent event)
{
//update the coordinates for the OnDraw method above, with wherever we touch
sx = event.getX();
sy = event.getY();
invalidate();
return true;
}
}
for the size you can easily call canvas.getWidth() and canvas.getHeight() and do all your values a percentage of those. Do never assume a constant!
You need to use two separate Paints to use two different colors. And remember that each paint is an object that needs initialisation.
// objects
private Paint drawPaint_WH = new Paint();
private Paint drawPaint_GR = new Paint();
// during construction
drawPaint_WH.setColor(Color.WHITE);
drawPaint_WH.setStyle(Style.FILL);
drawPaint_GR.setColor(Color. GREEN);
drawPaint_GR.setStyle(Style.FILL);
// and then during draw()
canvas.drawRect(100,100, 340,540, drawPaint_WH);
canvas.drawRect(0,0, 120,80, drawPaint_GR);
and then to make a triangle:
// object
private Path trianglePath;
// during construction
trianglePath = new Path();
trianglePath.moveTo(10, 10); // starting point
trianglePath.lineTo(10, 50); // 1st vertix
trianglePath.lineTo(50, 10); // 2nd vertix
trianglePath.lineTo(10, 10); // 3rd vertix and close
// then during draw()
canvas.drawPath(trianglePath, drawPaint_GR) // or whatever paint you want
ps.: do color the background it's easier to call canvas.drawColor(int colorVal);
So in the game I'm working on, I have a marble follow the mouse, but when it does this the screen flickers.
The background includes two jpegs and 9 rectangles. How would I go about double buffering this? Here is the code for the main window.
/**
* Write a description of class Window here.
*
* #author (your name)
* #version (a version number or a date)
*/
public class Window extends JApplet implements MouseMotionListener
{
private BufferedImage image;
private BufferedImage side;
private int mouseX;
private int mouseY;
public Window(){
try {
image = ImageIO.read(new File("Backgrounds/violet.jpg"));
side = ImageIO.read(new File("Backgrounds/side margin.jpg"));
} catch (IOException ex) { }
}
private void delay(int delay)
{
try {
Thread.sleep(delay);
} catch (InterruptedException e) {}
}
public void init()
{
this.addMouseMotionListener(this);
}
public void paint (Graphics page)
{
page.drawImage(image, 0, 0, null);
page.setColor(Color.blue);
page.fillRect(0, 0, 160, 160);
page.setColor(Color.black);
page.fillRect(15, 15, 130, 130);
page.setColor(Color.green);
page.fillRect(340, 0, 160, 160);
page.setColor(Color.black);
page.fillRect(355, 15, 130, 130);
page.setColor(Color.yellow);
page.fillRect(0, 340, 160, 160);
page.setColor(Color.black);
page.fillRect(15, 355, 130, 130);
page.setColor(Color.red);
page.fillRect(340, 340, 160, 160);
page.setColor(Color.black);
page.fillRect(355, 355, 130, 130);
page.drawImage(side, 500, 0, null);
page.drawString(Score.getScore(), 560, 110);
//conveyors
page.setColor(Color.gray);
page.fillRect(235, 0, 30, 160);
//marble
delay(100);
page.fillOval(mouseX, mouseY , 40, 40);
}
public void mouseMoved(MouseEvent e)
{
mouseX = e.getX();
mouseY = e.getY();
repaint();
}
public void mouseDragged(MouseEvent e)
{
}
}
Double buffering is conceptually pretty simple, instead of drawing your objects one by one, you draw them on an image and then tell the renderer to draw that entire image. This eliminates the flickering.
Here's an example of how you might do this (source)
class DoubleBufferedCanvas extends Canvas {
public void update(Graphics g) {
Graphics offgc;
Image offscreen = null;
Dimension d = size();
// create the offscreen buffer and associated Graphics
offscreen = createImage(d.width, d.height);
offgc = offscreen.getGraphics();
// clear the exposed area
offgc.setColor(getBackground());
offgc.fillRect(0, 0, d.width, d.height);
offgc.setColor(getForeground());
// do normal redraw
paint(offgc);
// transfer offscreen to window
g.drawImage(offscreen, 0, 0, this);
}
}
Nowdays, you don't have to implement this yourself, you can use the BufferStrategy and releated classes. See lakam99's answer for an example of that .
Swing supports double buffering automatically, so you don't need to code anything.
Just call setDoubleBuffered(true) on your top-level component (typically a JPanel) and it should all work.
See: setDoubleBuffered
Another solution is to use a library that will double buffer for you. Since you are using Java2D I am assuming you want to keep everything pretty lightweight and lower level. I think Slick2D does a great job of providing simple, 2d drawing and input functions without getting in your way. It feels like a more elegant version of Java2D, but is written on OpenGL. Once you make a few applications with pure Java, I think moving to Slick2D is a GREAT idea. This is not a direct solution to your issue, but since it has already been solved I thought Id offer some advice that will make your Java game development life easier. Check it out if you get a chance http://slick.cokeandcode.com/
I think your problem is not double buffering. You must add super.paint(page); at the first line of your paint method.