I am making an app that currently only make squares move on a "road" and make random desicions on where to go. Now I want to replace them with a image of a car.
I'm currently using the "onDraw(Canvas canvas)" method. confused
So how do I import images to the app.
And how do I do If I want it to animate with 2-3 images.
Easyer explained. I want to replace the drawRect with drawImage or drawBitmap and make it work. I want to load the image from the drawable folder.
Code:
@Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setColor(android.graphics.Color.RED);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(square1.x, square1.y, square1.x + 20, square1.y + 20,
paint);
paint.setColor(android.graphics.Color.BLUE);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(square2.x, square2.y, square2.x + 20, square2.y + 20, paint);
paint.setColor(android.graphics.Color.GREEN);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(square3.x, square3.y, square3.x + 20, square3.y + 20,
paint);
paint.setColor(android.graphics.Color.BLACK);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(square4.x, square4.y, square4.x + 20, square4.y + 20,
paint);
paint.setColor(android.graphics.Color.YELLOW);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(square5.x, square5.y, square5.x + 20, square5.y + 20,
paint);
Generally the easiest way to animate a limited number of frames on any system is using clip rectangles and a single image that contains the frames side by side... depending on the system this doesn't even create a whole let of overhead if you use an uncompressed format like TGA or BMP, laid out vertically. Is there anything specific you need to know about that... or is your problem with the timing? You could just use the nanotime and decide which frame to draw based on y=(time%fullAnimationTime)/frameTime*tileHeight
That will be my problem in the future.
But right now I don't know how to even import and use images properly.
I'm very new at programming for android. Have only programmed a little java before
Just read up a little on this... seems AnimationDrawable actually does exactly what you need, just look it up in the reference.
If you still want to do the side-by-side thing I suggested first, here's some code to get you started, which uses assets to access a BMP. You still need a timer to actually cause the drawing, but I guess you've already set that up:
Code:
Bitmap animBmp=null;
try {
InputStream animStream=null;
animStream=this.getAssets().open("anim.bmp");
BufferedInputStream animBufStream = new BufferedInputStream(animStream);
animBmp = BitmapFactory.decodeStream(animBufStream);
animBufStream.close();
animStream.close();
} catch (IOException e) {
e.printStackTrace();
}
class AnimView extends View{
public int frameTime=100;
public int frames=-1;
public int frameWidth=0;
public int frameHeight=0;
public Bitmap animBmp=null;
public Paint paint=null;
private int lastFrame=-1;
public AnimView(Context ctx, Bitmap bmp,int frms) {
super(ctx);
animBmp=bmp;
frames=frms;
frameWidth=bmp.getWidth();
frameHeight=bmp.getHeight()/frames;
paint=new Paint();
}
protected void onDraw(Canvas c){
Log.i("draw", "draw");
int frame=(int)((SystemClock.elapsedRealtime()%(frameTime*frames))/frameTime);
if(frame!=lastFrame){
c.drawBitmap(animBmp, new Rect(0,frame*frameHeight,frameWidth,(frame+1)*frameHeight), new Rect(0,0,frameWidth,frameHeight),paint);
lastFrame=frame;
}
}
};
AnimView v=new AnimView(this,animBmp,3);
It says that
"animStream=this.getAssets().open("anim.bmp");"
The method getAssets() is undefined for the type MyTimedView
I am a real noob at this. Where am I suppose to set my test.bmp? (The image is named test) Which variables should I change for it to understand that it always should use the "test" image?
Also. I have a image of a house that I want to be placed on the screen. And this that you gave me doesn't help me there I think?
Thanks for all your help!!
getAssets operates on the Activity, not the View.
Change this line to your bitmap's path:
animStream=this.getAssets().open("anim.bmp");
in your case
animStream=this.getAssets().open("test.bmp");
You'll also have to change this line to match the actual number of frames:
AnimView v=new AnimView(this,animBmp,3);
And lastly, the file (test.bmp) should be inside the ASSETS directory of your eclipse project.
Ok I have done everything you have said. I made 3 images and stored them in assets. Named test1, test2, test3. But now I only get a white screen. I had some stuff from the beginning but they are now gone. And I don't get a image or anything.
Even more complex. How do I set the X and Y values to the animation?
It's supposed to be one image with the frames ontop of each other. Give me a second... I'll pack it into a project and attach it.
Here you go. I added a few comments:
Code:
package net.tapperware.simpleanimation;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.View;
public class SimpleAnimationActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//This will hold our single bitmap which will contain all frames stacked ontop of each other
Bitmap animBmp=null;
try {
//First, load the file: This is supposed to be in the assets folder of the project
InputStream animStream=this.getAssets().open("anim.bmp");
//BitmapFactory needs a BufferedInputStream, so let's just convert our InputStream
BufferedInputStream animBufStream = new BufferedInputStream(animStream);
//OK, now we decode it to an Android-Bitmap
animBmp = BitmapFactory.decodeStream(animBufStream);
//And finally, we clean up
animBufStream.close();
animStream.close();
} catch (IOException e) {
e.printStackTrace();
}
//This will be used to operate the loop... looping on Android needs a Runnable, and this class provides it. When
//run, it will invalidate the view, which causes onDraw to be called.
class AnimLoop implements Runnable{
private View view;
AnimLoop(View v){ view=v; }
@Override public void run() { view.invalidate(); }
}
//And here the actual view
class AnimView extends View{
//Time between frames
public int frameTime=100;
//Number of frames
public int frames=-1;
//Width of each frame
public int frameWidth=0;
//Height of each frame
public int frameHeight=0;
//The previous frame number shown
public int lastFrame=0;
//This is our Runnable that will call invalidate()
public AnimLoop loop=null;
//Of course, the actual Bitmap
public Bitmap animBmp=null;
//Just a default Paint object, since it's required by drawBitmap
public Paint paint=null;
public AnimView(Context ctx, Bitmap bmp,int frms) {
super(ctx);
//Assign the args to our attributes
animBmp=bmp;
frames=frms;
//Since the images are stacked ontop of each other, each frame is widthOfBitmap * (heightOfBitmap / numberOfFrames )
frameWidth=bmp.getWidth();
frameHeight=bmp.getHeight()/frames;
//And finally, our dummy height
paint=new Paint();
//And the Runnable that will cause invalidate to be called
loop=new AnimLoop(this);
}
protected void onDraw(Canvas c){
//Draw the rect that corresponds to the current frame
c.drawBitmap(
animBmp
//We need to move down by frame number*the frame index
,new Rect(0,lastFrame*frameHeight,frameWidth,(lastFrame+1)*frameHeight)
//This is our target rect... draw wherever you want
,new Rect(0,0,frameWidth,frameHeight)
//And our standard paint settings
,paint);
//Increase the frame number by one, if it's >= the total number of frames, make it wrap back to 0
lastFrame=(lastFrame+1)%frames;
//And ask for the next frame to be drawn in frameTime milliseconds.
this.getHandler().postDelayed(loop, frameTime);
}
};
//Arguments: Activity/Context , Bitmap, Frame Count
AnimView v=new AnimView(this,animBmp,3);
setContentView(v);
}
}
[2011-08-21 01:53:39 - SimpleAnimation] ERROR: Application requires API version 10. Device API version is 8 (Android 2.2).
[2011-08-21 01:53:39 - SimpleAnimation] Launch canceled!
Right now I feel like a 10 year old that doesn't understand how to spell.
Any quickfix to make it 2.2 compatible?
Yep, go to Project /Properties /Android and set the checkmark somewhere else... the code is not using any of it, I just set it to something. Any 2.x should be fine, probably even 1.x
Thanks for all your awsome work!
But I have 1 problem. The picture. anim.bmp never gets placed on the screen. I have altered the x and y values but it seems like it's never getting loaded. I have changed all that I thought needed to be changed.
Lets keep this simple. After I am done with the above. I want to make 1 image on a specific x and y. And I want it to be clickable. Nobody really goes into detail about how to even get a picture into the app. Everyone believes it's so simple...
That's... troubling. You mean the unchanged project right? It works perfectly here and I can't see anything that would cause issues with the code, so it must be the project setup. Could you open the compiled APK with WinRAR or 7zip and verify that there is indeed a folder named assets, containing anim.bmp?
It's supposed to appear at 0,0... to move it, you'd have to change this line
,new Rect(0,0,frameWidth,frameHeight)
to
,new Rect(desiredX,desiredY,desiredX+frameWidth,desiredY+frameHeight)
I'm not really qualified to tell you how to work with resources... I just plain don't like the system, so I usually work around it and use assets instead, which are simply put into the assets folder and that's the end of it (BUT, they don't have any automatic resolution handling, so you have to implement that yourself).
Yay it worked! If I would want to use this code for my app, do I create a new class for it or just dump everything in activitys? Because right now when I dumped it in activitys it just made a white screen. No animation or anything. It's just printing out the backround.
Phew! Your code will usually consist of a bunch of classes which inherit from View, which should each be contained in their own file. This AnimView will just be one more class among your collection.
According to the guidelines, you should then reference your Classes in res/layout/*.xml, but I've never done that (this strange, broken thing that Android calls XML gives me a headache), so well... you've got to find out how to do that without my help.
Why does it still give me a white screen? It is now back to the original and no new view is implemented.
I know my code looks horrible.
You load R.layout.main... but from what I can tell, there's nothing in there?
It is suppose to be loaded I think. If you mean when it is activitys.
And yes it isn't that much code. I recently started.
Where?:
StepByStepActivity:
Code:
public class StepByStepActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
(...)
setContentView(R.layout.main);
}
}
This loads R.layout.main... as far as I can tell, that's the only thing being executed on load, aside from a few config changes.
res/layout/main.xml:
Code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
(...) android:id="@+id/mainlayout" (...)>
</LinearLayout>
That defines a linear layout.... but where is its content
This is the content. 5 squares and some lines drawed so it would be easyer to see where they are suppose to go.
Code:
@Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setColor(android.graphics.Color.RED);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(square1.x, square1.y, square1.x + 20, square1.y + 20,
paint);
paint.setColor(android.graphics.Color.BLUE);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(square2.x, square2.y, square2.x + 20, square2.y + 20, paint);
paint.setColor(android.graphics.Color.GREEN);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(square3.x, square3.y, square3.x + 20, square3.y + 20,
paint);
paint.setColor(android.graphics.Color.BLACK);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(square4.x, square4.y, square4.x + 20, square4.y + 20,
paint);
paint.setColor(android.graphics.Color.YELLOW);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(square5.x, square5.y, square5.x + 20, square5.y + 20,
paint);
paint.setStrokeWidth(3);
paint.setColor(android.graphics.Color.BLACK);
paint.setStyle(Paint.Style.FILL);
canvas.drawLine(95, 200, 650, 200, paint);
// 6 Vågrät
paint.setStrokeWidth(3);
paint.setColor(android.graphics.Color.BLACK);
paint.setStyle(Paint.Style.FILL);
canvas.drawLine(100, 200, 100, 480, paint);
// 5 lodrät
paint.setStrokeWidth(3);
paint.setColor(android.graphics.Color.BLACK);
paint.setStyle(Paint.Style.FILL);
canvas.drawLine(650, 200, 650, 480, paint);
// 4 lodrät
paint.setStrokeWidth(3);
paint.setColor(android.graphics.Color.BLACK);
paint.setStyle(Paint.Style.FILL);
canvas.drawLine(600, 0, 600, 200, paint);
// 3 lodrät
paint.setStrokeWidth(3);
paint.setColor(android.graphics.Color.BLACK);
paint.setStyle(Paint.Style.FILL);
canvas.drawLine(340, 200, 340, 480, paint);
// 2 lodrät
paint.setStrokeWidth(3);
paint.setColor(android.graphics.Color.BLACK);
paint.setStyle(Paint.Style.FILL);
canvas.drawLine(180, 0, 180, 200, paint);
// 1 lodrät
}
I've done a lot of coding of shader with GL and DX over the years so I thought I'll knock up a simple rotating cube on my phone. For me this really is a 10 minute job. 2 hours later I was stumped..........
The shader is just a transforms of the xyz and copy of the vertex colour. This works fine with one matrix. When I separated the model matrix out so now I upload a view*invcam matrix and a model matrix it all failed. After some hacking about I got to a point where just adding the one extra mat4 uniform stopped the shader from working. Feels like a bug in the OS, anyone know of Samsung GLES 2.0 shader bugs? I'm at work at the moment but later I'll post the shader. It really is "my first shader" simple stuff.
Here is my pixel and vertex shaders, very simple.
If I uncomment out the line "uniform mat4 trans;" the shader stops working.
Code:
precision highp float;
uniform mat4 proj_cam; //This is the projection * invcam matrix.
//uniform mat4 trans; //This is model to world space.
attribute vec4 vPosition;
attribute vec4 vColour;
varying vec4 v_colour; //The colour that is passed to the pixel shader.
void main()
{
gl_Position = proj_cam * vPosition;
v_colour = vColour;
}
Code:
precision mediump float;
varying vec4 v_colour; //The colour that is passed to the pixel shader.
void main()
{
gl_FragColor = v_colour;
}
So if I change the shader to use an array of matrices and upload the two matrices from one float[32] array it works...
Code:
precision highp float;
uniform mat4 proj_cam[2];
attribute vec4 vPosition;
attribute vec4 vColour;
varying vec4 v_colour;
void main()
{
gl_Position = proj_cam[0] * (proj_cam[1] * vPosition);
v_colour = vColour;
}
I smell an OS bug............
Questions or Problems Should Not Be Posted in the Development Forum
Please Post in the Correct Forums
Moving to Q&A
Sorry, I don't understand. This is a software development question, why move to the Q&A thread? Did I not post it in the software development forum?????
Just rewrote my test application in c/c++ (I think that is software development? ) with the NDK and it works so Samsung must have broken the GL2 mapping to the native code side in their version of the API.
I don't really need to work in c/c++ so thought using Java would allow rapid prototyping. Guess not seeing it's broken...........
I am in an introduction to programming class and have some questions on a script I am working on. Anyone familiar with the Ruby
(.rb) language. Thanks
Sent from my Nexus 7 using xda app-developers app
Not really sure why this is in the Rezound QA...
I'm not familiar with Ruby (other than just looking at some code a few times)... but what's the issue you're having exactly?
lol I figured I would get that exact response, but it seemed like a good place to ask to be honest. I have this set of code here, Im not cut out for programming and was looking for help this is the pseudocode for the project I am working on.
MAXLINELENGTH = 40
codes = ['.-', '-...', '-.-.', '-..', '.', '..-.',
'--.', '....', '..', '.---', '-.-', '.-..',
'--', '-.', '---', '.--.', '--.-', '.-.',
'...', '-', '..-', '...-', '.--', '-..-',
'-.--', '--..','.----', '..---', '...--',
'....-', '.....', '-....', '--...', '---..',
'----.', '-----']
chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
f1 = File.open("index.txt", "w")
f2 = File.open("index.txt", "r")
Initialize line_length = 0
while character = fin.getc
if index = chars.index(character.upcase)
code.getc
Print code to fout
Print " " to fout
line_length = line_length + code.length + 2
end
elsif character == " "
Print " " to. fout
line_length += code.lenght + 4
end
if line_length >= MAXLINELENGTH
Print new line character to fout.print "\n"
Reset line_length to 0
end
end
fout.close
fin.close
Basically the goal is to print letters and numbers to a documnet labeled idex.txt but the user input characters would be translated in morse code in the txt document
zkrp5108 said:
lol I figured I would get that exact response, but it seemed like a good place to ask to be honest. I have this set of code here, Im not cut out for programming and was looking for help this is the pseudocode for the project I am working on.
MAXLINELENGTH = 40
codes = ['.-', '-...', '-.-.', '-..', '.', '..-.',
'--.', '....', '..', '.---', '-.-', '.-..',
'--', '-.', '---', '.--.', '--.-', '.-.',
'...', '-', '..-', '...-', '.--', '-..-',
'-.--', '--..','.----', '..---', '...--',
'....-', '.....', '-....', '--...', '---..',
'----.', '-----']
chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
f1 = File.open("index.txt", "w")
f2 = File.open("index.txt", "r")
Initialize line_length = 0
while character = fin.getc
if index = chars.index(character.upcase)
code.getc
Print code to fout
Print " " to fout
line_length = line_length + code.length + 2
end
elsif character == " "
Print " " to. fout
line_length += code.lenght + 4
end
if line_length >= MAXLINELENGTH
Print new line character to fout.print "\n"
Reset line_length to 0
end
end
fout.close
fin.close
Basically the goal is to print letters and numbers to a documnet labeled idex.txt but the user input characters would be translated in morse code in the txt document
Click to expand...
Click to collapse
So your taking input and converting to Morse code then logging it to a text document? Never tried that language but it looks similar to visual basic.
If so, I don't see a loop set up to parse through the input string. You will need to iterate through each character, then I'm assuming there is a separate class (or function?) that will return the Morse code for each character.
Sorry I've only ever used c++ and java
Sent from my ADR6425LVW using xda app-developers app
Squirrel1620 said:
So your taking input and converting to Morse code then logging it to a text document? Never tried that language but it looks similar to visual basic.
If so, I don't see a loop set up to parse through the input string. You will need to iterate through each character, then I'm assuming there is a separate class (or function?) that will return the Morse code for each character.
Sorry I've only ever used c++ and java
Sent from my ADR6425LVW using xda app-developers app
Click to expand...
Click to collapse
Yea Im really bad at this, I was super excited to learn it but its not going well. I cant think in a rules and order kinda thing, I'm just more free thinking I need to be able to change stuff to however I want. So I just don't understand what I am looking at lol.
zkrp5108 said:
Yea Im really bad at this, I was super excited to learn it but its not going well. I cant think in a rules and order kinda thing, I'm just more free thinking I need to be able to change stuff to however I want. So I just don't understand what I am looking at lol.
Click to expand...
Click to collapse
Well I'm self taught I guess it's just a personality thing lol. Basically think of coding like this : write this program : make a pb+j sandwich, literally write down EVERY step you need to do in order to make it... Kinda weird analogy, but depending on how deep you go that could end up being tens of thousands of lines of code.
So in your case write down on paper EVERY step you need to do to get morse code from the input and write it to a text file. That will be your pseudocode now you need to translate that into code. Remember Google is your friend when you need to find the syntax needed to do what you want.
Wish I had more free time and experience in ruby to help
Sent from my ADR6425LVW using xda app-developers app
Easiest thing to do, will be to loop through the entire input string and parse each letter at a time. Had to do a morse-code conversion program in several older languages (Pascal, Fortran, Ada, C, C++) for my Programming Languages course last semester. Pseudocode was something like:
Get input from user (or parse an input file).
Store input into a string (or a string array if multiple lines).
Loop through string and check each letter individually and look up what the morse-code equivalent is.
Store the morse code equivalent in a new string inside the loop.
When you hit the end of the string (end of the loop), save the morse string to a file.
In the loop, checking each individual letter, a case statement (or if else-if else's) will be the easiest (more typing, but easier logic).
So, for example, here's a C++ version that I wrote for my class last semester:
Code:
#include <cstdlib>
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
string search(char character);
int main()
{
string encryptionString = "";
string morseString = "";
cout << "Enter a sentence, containing only letters and blanks \nand ending with a period, to convert to morse code: " << endl;
getline(cin, encryptionString);
//remove ending period, if it exists
if(encryptionString[encryptionString.length() - 1] == '.')
{
encryptionString.erase(encryptionString.length() - 1);
}//if
for(int i = 0; i < encryptionString.length(); i++)
{
encryptionString[i] = toupper(encryptionString[i]);
}//for
int index = 0;
while(index < encryptionString.length())
{
if(encryptionString[index] != ' ' || encryptionString[index] != '\n')
{
cout << " ";
morseString = search(encryptionString[index]);
cout << morseString;
}
else
{
cout << endl;
morseString = "";
}
index++;
}//while
cin.ignore();
cout << "\n\nPress enter to exit...";
cin.get();
return 0;
}//main
string search(char character)
{
string returnString = "";
if(character >= 65 || character <= 90 )
{
switch(character)
{
case 'A':
returnString = ".-";
break;
case 'B':
returnString = "-...";
break;
case 'C':
returnString = "-.-.";
break;
case 'D':
returnString = "-..";
break;
case 'E':
returnString = ".";
break;
case 'F':
returnString = "..-.";
break;
case 'G':
returnString = "--.";
break;
case 'H':
returnString = "....";
break;
case 'I':
returnString = "..";
break;
case 'J':
returnString = ".---";
break;
case 'K':
returnString = "-.-";
break;
case 'L':
returnString = ".-..";
break;
case 'M':
returnString = "--";
break;
case 'N':
returnString = "-.";
break;
case 'O':
returnString = "---";
break;
case 'P':
returnString = ".--.";
break;
case 'Q':
returnString = "--.-";
break;
case 'R':
returnString = ".-.";
break;
case 'S':
returnString = "...";
break;
case 'T':
returnString = "-";
break;
case 'U':
returnString = "..-";
break;
case 'V':
returnString = "...-";
break;
case 'W':
returnString = ".--";
break;
case 'X':
returnString = "-..-";
break;
case 'Y':
returnString = "-.--";
break;
case 'Z':
returnString = "--..";
break;
}//switch
}//if
return returnString;
}//search
For you, you would instead print to a file instead of print to screen. You'll need to look up the exact syntax for Ruby, but should be easy.