I'm making a very very simple game in Android, and I'm not using OpenGL or any other libraries, just Java!
Now I'm stuck in designing my map...
I want to design something like this:
(Those lines should consider as walls and players can't get out of them)
How to design something like this using XML only? Or I should start using Unity3D?
This isn't done with xml, but you neither need any libraries.
public class Background extends View {
private static final int BORDER_WIDTH = 2; //in px
private int[] points; //2n = x, 2n+1 = y
public Background(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for(Drawable drawable : drawBackground()){
drawable.draw(canvas);
}
}
private Drawable[] drawBackground() {
Drawable[] drawables = new Drawable[2];
int width = getWidth();
int height = getHeight();
int corner = width / 4;
//draw border
Path path = new Path();
path.moveTo(0, corner);
path.lineTo(corner, 0);
path.lineTo(width, 0);
path.lineTo(width, height - corner);
path.lineTo(width - corner, height);
path.lineTo(0, height);
path.close();
drawables[0] = new ShapeDrawable(new PathShape(path, width, height));
drawables[0].setBounds(0, 0, width, height);
//draw inside the border
points = {
BORDER_WIDTH, corner,
corner, BORDER_WIDTH,
width - BORDER_WIDTH, BORDER_WIDTH,
width - BORDER_WIDTH, height - corner,
width - corner, height - BORDER_WIDTH,
BORDER_WIDTH, height - BORDER_WIDTH
}
path = new Path();
path.moveTo(points[0], points[1]);
for (int i = 2, i < points.length, i++) {
path.lineTo(points[i], points[++i]);
}
path.close();
ShapeDrawable shapeDrawable = new ShapeDrawable(new PathShape(path, width, height));
shapeDrawable.getPaint().setColor(Color.rgb(238, 238, 238));
shapeDrawable.setBounds(0, 0, width, height);
drawables[1] = shapeDrawable;
return drawables;
}
public Point[] getPoints() {
return points;
}
}
The result:
Related
Because of my design, i want to get rid of NinePatch object, but i use it to initialize textures at the desired size using framebuffer, and then apply that textures to my custom objects
Im new to LibGDX and GL stuff.
The problem is when i draw FBO texture to screen the image is so small, idk why
I grab skeleton of all this from here: https://stackoverflow.com/a/7632680/401529
My RenderToTexture class is:
public class RenderToTexture {
private float fbScaler = 1f;
private boolean fbEnabled = true;
private FrameBuffer fb = null;
private TextureRegion fbReg = null;
[... more constructors ... ]
/**
*
* #param scale
*/
public RenderToTexture(int width, int height, float scale, boolean hasDepth) {
if(width == -1){
width = (int) (Gdx.graphics.getDisplayMode().width * scale);
}
if(height == -1){
height = (int) (Gdx.graphics.getDisplayMode().height * scale);
}
fb = new FrameBuffer(
Pixmap.Format.RGBA8888,
(int)(width * fbScaler),
(int)(height * fbScaler),
hasDepth
);
fbReg = new TextureRegion(fb.getColorBufferTexture());
fbReg.flip(false,false);
}
public void begin(){
if(fbEnabled) {
fb.begin();
Gdx.gl.glClearColor(0, 0,0,0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
}
}
public TextureRegion end(){
if(fb != null)
{
fb.end();
return fbReg;
// batch.draw(fboRegion, 0, 0);
}
return null;
}
}
And my util class:
public class ImageUtils {
public static TextureRegion ninePatchToTextureRegion(NinePatch patch, int width, int height){
return ninePatchToTextureRegion(new NinePatchDrawable(patch), width, height);
}
public static TextureRegion ninePatchToTextureRegion(NinePatchDrawable patch, int width, int height){
RenderToTexture r2t = new RenderToTexture(width, height, 1, false);
SpriteBatch sb = new SpriteBatch();
r2t.begin();
sb.begin();
patch.draw(sb, 0, 0, width, height);
sb.end();
sb.dispose();
return r2t.end();
}
}
Then i call this util class when i create a sprite:
NinePatchDrawable ninepatchtest = new NinePatchDrawable(
new NinePatch(new Texture(Gdx.files.internal("img/ui/btn-retro-blue.png")), 5, 5, 5, 5)
);
TextureRegion result = ImageUtils.ninePatchToTextureRegion(ninepatchtest, 200, 100);
sprite = new Sprite(result);
The current result is (left) and the size simulated desired result (right)
EDIT: Camera size is displaymode size, glued to screen, no zoom, no movement.
EDIT: Fixed missing dispose suggested by #Tenfour04
If this way is not the best way to do it, im open to new alternatives
Well i found a "HALF" solution of my problem:
As i see here in this example LibGDX - Drawing to a FrameBuffer does not work i miss the setProjectionMatrix to SpriteBatch object, so render to texture class begin() method now is:
public SpriteBatch begin(){
SpriteBatch batch = null;
if(fbEnabled) {
fb.begin();
Gdx.gl.glClearColor(0, 0,0,0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Matrix4 m = new Matrix4();
m.setToOrtho2D(0, 0, fb.getWidth(), fb.getHeight());
batch = new SpriteBatch();
batch.setProjectionMatrix(m);
}
return batch;
}
Now renderToTexture begin() returns spritebatch, so:
public static TextureRegion ninePatchToTextureRegion(NinePatchDrawable patch, int width, int height){
RenderToTexture r2t = new RenderToTexture(width, height, 1, false);
SpriteBatch sb = r2t.begin();
sb.begin();
patch.draw(sb, 0, 0, width, height);
sb.end();
sb.dispose();
return r2t.end();
}
This solves the size of drawed texture from FBO, but ninepatch is drawed ok outside framebuffer, and stretched with framebuffer...
I am having a problem with the libGDX engine. I have a pair of variables to set the width and height of the screen, and another pair to set the width and height of the camera. However, whenever the camera is not the same size as the screen, the engine will not render any sprites. Here is my code for you to look at:
My Constants:
public abstract class Constants
{
public static final int WINDOW_WIDTH = 800;
public static final int WINDOW_HEIGHT = 600;
public static final int CAMERA_WIDTH = 800;
public static final int CAMERA_HEIGHT = 600;
}
Where the Sprite is Created:
public class GameController
{
public static final String TAG = GameController.class.getName();
public Sprite[] testSprites;
public int selectedSprite;
public GameController()
{
init();
}
private void init()
{
initTestObjects();
}
private void initTestObjects()
{
testSprites = new Sprite[1];
int width = 32;
int height = 32;
Pixmap pixmap = createProceduralPixmap(width, height);
Texture texture = new Texture(pixmap);
for(int i = 0; i < testSprites.length; i++)
{
Sprite spr = new Sprite(texture);
spr.setSize(32, 32);
spr.setOrigin(spr.getWidth() / 2.0f, spr.getHeight() / 2.0f);
spr.setPosition(0, 0);
testSprites[i] = spr;
}
selectedSprite = 0;
}
private Pixmap createProceduralPixmap(int width, int height)
{
Pixmap pixmap = new Pixmap(width, height, Format.RGBA8888);
pixmap.setColor(1, 0, 0, 0.5f);
pixmap.fill();
pixmap.setColor(1, 1, 0, 1);
pixmap.drawLine(0, 0, width, height);
pixmap.drawLine(width, 0, 0, height);
pixmap.setColor(0, 1, 1, 1);
pixmap.drawRectangle(0, 0, width, height);
return pixmap;
}
public void update(float deltaTime)
{
updateTestObjects(deltaTime);
}
public void updateTestObjects(float deltaTime)
{
float rotation = testSprites[selectedSprite].getRotation();
rotation += 90 * deltaTime;
rotation %= 360;
testSprites[selectedSprite].setRotation(rotation);
}
}
And the Drawing:
public class GameRenderer implements Disposable
{
public static final String TAG = GameRenderer.class.getName();
private OrthographicCamera camera;
private SpriteBatch batch;
private GameController gameController;
public GameRenderer(GameController gameController)
{
this.gameController = gameController;
init();
}
private void init()
{
batch = new SpriteBatch();
camera = new OrthographicCamera(Constants.CAMERA_WIDTH,
Constants.CAMERA_HEIGHT);
camera.position.set(0, 0, 0);
camera.update();
}
public void render()
{
renderTestObjects();
}
private void renderTestObjects()
{
batch.setProjectionMatrix(camera.combined);
batch.begin();
for(Sprite sprite : gameController.testSprites)
{
sprite.draw(batch);
}
batch.end();
}
public void resize(int width, int height)
{
camera.viewportWidth =
(Constants.CAMERA_HEIGHT / height) * width;
camera.update();
}
#Override
public void dispose()
{
batch.dispose();
}
}
The code above works fine and will render a sprite in the center of the screen, but when I change CAMERA_WIDTH and CAMERA_HEIGHT to say 80 and 60 respectively, instead of making the sprite 10x larger like it should, it doesn't draw anything. Any advice?
You are dividing ints by ints, so you end up with poorly scaled numbers. For example:
camera.viewportWidth =
(Constants.CAMERA_HEIGHT / height) * width;
If the screen width and height are 800 and 600, and CAMERA_HEIGHT is 60, then the equation becomes
camera.viewportWidth =
(60 / 600) * 800;
which becomes (due to pure integer math):
camera.viewportWidth =
(0) * 800;
which becomes 0. You need to cast those ints to floats before dividing! This may not be the only issue, but it alone could be causing your problem.
I am having problems displaying dots on the outer ring of a circle. When a dot is placed at one of the edges of the circle, the dot is half cut off . Screenshot: https://drive.google.com/file/d/0B9BaYaKRY3v3Y2hXYkpSOE1nY28/edit?usp=sharing
I simply want to make the circles radius a litte smaller so there is some space around it where the outer dots have got some space. Of course the circle must still stay in the middle of the view. Tipps on how to do this are very appreciated.
The working code blow is fully working accept for the fact that the dots are being cut off. (Thanks to #Sherif elKhatib for the help on creating a 2 color circle)
public class PercentView extends View {
public PercentView(Context context) {
super(context);
init();
}
public PercentView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PercentView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
paint = new Paint();
paint.setColor(Color.parseColor("#3498db"));
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);
bgpaint = new Paint();
bgpaint.setColor(Color.parseColor("#2980b9"));
bgpaint.setAntiAlias(true);
bgpaint.setStyle(Paint.Style.FILL);
rect = new RectF();
circlePaint = new Paint();
}
Paint paint;
Paint bgpaint;
RectF rect;
float percentage = 5;
Paint circlePaint;
float[] dots = new float[1000];
int dotsNum = -1;
String[] colorCode = new String[1000];
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// draw background circle anyway
canvas.drawArc(rect, -90, 360, true, bgpaint);
if (percentage != 0) {
int left = 0;
int width = getWidth();
int top = 0;
rect.set(left, top, left + width, top + width);
canvas.drawArc(rect, -90, (float) (3.6 * percentage), true, paint);
for (int i = 0; i <= dotsNum; i++) {
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.parseColor(colorCode[i]));
circlePaint.setStyle(Paint.Style.FILL);
float dotX = (float) (this.getWidth() / 2 + this.getWidth() / 2
* Math.cos((dots[i] * 3.6 - 90) * Math.PI / 180));
float dotY = (float) (this.getHeight() / 2 + this.getWidth()
/ 2 * Math.sin((dots[i] * 3.6 - 90) * Math.PI / 180));
canvas.drawCircle(dotX, dotY, 30, circlePaint);
}
}
}
public void setPercentage(float inpercentage) {
this.percentage = inpercentage;
invalidate();
}
public void setDot(int type) {
dotsNum++;
switch (type) {
case 0:
colorCode[dotsNum] = "#27ae60";
break;
case 1:
colorCode[dotsNum] = "#f1c40f";
break;
case 2:
colorCode[dotsNum] = "#e74c3c";
break;
case 3:
colorCode[dotsNum] = "#34495e";
break;
}
dots[dotsNum] = percentage;
invalidate();
}
}
The only one working approach for me was that piece of code "width = getWidth() - padding". Kudos #Catherine.
I'm trying to use the ShadowRenderer from swingx to create a shadow for a panel. Here is what i did so far:
Creating the shadow renderer one time in the panel constructor.
public CustomPanel() {
super();
renderer = new ShadowRenderer(20, 0.5f, Color.RED);
}
Each time the panel is resized, i recalculate the new shadow.
#Override
public void setBounds(int x, int y, int width, int height) {
super.setBounds(x, y, width, height);
shadow = renderer.createShadow(GraphicsUtilities.createCompatibleTranslucentImage(width, height));
}
And then i override the paintComponent method of my panel to draw the generated image:
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.drawImage(shadow, 0, 0, null);
//super.paintComponent(g);
}
But the shadow image is never shown. Why? I read this and i except my code to draw a kind of "shadowed" image generated by the shadow renderer.
Here's a shortened example of DropShadowDemo
JXPanel panel = new JXPanel() {
int shadowSize = 40;
ShadowRenderer renderer = new ShadowRenderer(shadowSize/ 2, 0.5f, Color.RED);
BufferedImage imageA =
XTestUtils.loadDefaultImage("moon.jpg");
BufferedImage shadow;
#Override
public void setBounds(int x, int y, int width, int height) {
super.setBounds(x, y, width, height);
// not really needed here - the base image size is fixed
shadow = renderer.createShadow(imageA);
}
#Override
protected void paintComponent(Graphics g) {
int x = (getWidth() - imageA.getWidth()) / 2;
int y = (getHeight() - imageA.getHeight()) / 2;
Graphics2D g2 = (Graphics2D) g;
Composite c = g2.getComposite();
g2.setComposite(AlphaComposite.SrcOver.derive(renderer.getOpacity()));
g.drawImage(shadow, x - shadowSize / 2, y - shadowSize / 2, null);
g2.setComposite(c);
g.drawImage(imageA, x, y, null);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(imageA.getWidth() + shadowSize, imageA.getHeight()+ shadowSize);
}
};
panel.setOpaque(false);
So far, my image starts at 0,0 and scales properly. There is a black bar under it. How can I align it so that it is centered along the y, with a black bar above and below the image?
edit: also, what are "this.getWidth(), this.getHeight()" referring to when I make the object "dest" - the width of mBitmap? The documentation does say they represent the width of the view, I just want to make sure I'm correct in thinking that is it mBitmap.
public class SpotGameActivity extends Activity {
private Bitmap mBitmap;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dpi2b);
setContentView(new BitMapView(this, mBitmap));
}
class BitMapView extends View {
Bitmap mBitmap = null;
public BitMapView(Context context, Bitmap bm) {
super(context);
mBitmap = bm;
}
#Override
protected void onDraw(Canvas canvas) {
//DisplayMetrics metrics = new DisplayMetrics();
//getWindowManager().getDefaultDisplay().getMetrics(metrics);
// called when view is drawn
Paint paint = new Paint();
paint.setFilterBitmap(true);
// The image will be scaled so it will fill the width, and the
// height will preserve the image’s aspect ration
float aspectRatio = ((float) mBitmap.getWidth()) / mBitmap.getHeight();
Rect dest = new Rect(0, 0, this.getWidth(),(int) (this.getWidth() / aspectRatio));
String AR = Double.toString(aspectRatio);
canvas.drawBitmap(mBitmap, null, dest, paint);
Toast.makeText(SpotGameActivity.this, AR, Toast.LENGTH_SHORT).show();
}
I've now gotten the difference between the view size and image size. I've divided the difference by 2 but now, my image is align to the bottom of the screen rather than the middle of the y-axis. any tips?:
#Override
protected void onDraw(Canvas canvas) {
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int scrHeight = this.getHeight();
String sH = Integer.toString(scrHeight);
Log.v(TAG, "scrHeight =" + sH );
int imgHeight= mBitmap.getHeight();
String iH = Integer.toString(imgHeight);
Log.v(TAG, "imgHeight =" + iH );
int diff = scrHeight - imgHeight;
String dif = Integer.toString(diff);
Log.v(TAG, "diff =" + dif );
int dvd= diff/2;
// called when view is drawn
Paint paint = new Paint();
paint.setFilterBitmap(true);
// The image will be scaled so it will fill the width, and the
// height will preserve the image’s aspect ration
float aspectRatio = ((float) mBitmap.getWidth()) / mBitmap.getHeight();
Rect dest = new Rect(0, dvd, this.getWidth(),(int) (this.getWidth() / aspectRatio)+dvd);
String AR = Double.toString(dvd);
canvas.drawBitmap(mBitmap, null, dest, paint);
Toast.makeText(SpotGameActivity.this, AR, Toast.LENGTH_SHORT).show();