开发者

Making my canvas scroll-able without a major overhaul

开发者 https://www.devze.com 2023-03-14 05:52 出处:网络
I\'m in the process of developing a 2-D game for android which primarily i\'m using as an experience to learn the in\'s and out\'s of programming for android apps, so naturally i run into a lot of puz

I'm in the process of developing a 2-D game for android which primarily i'm using as an experience to learn the in's and out's of programming for android apps, so naturally i run into a lot of puzzles to work through. Currently, my main activity instantiates a custom class which extends SurfaceView and implements SurfaceHolder.Callback. This view instantiates a thread which handles most of the logic and all the graphics processing (this includes instantiating a canvas and drawing to it., etc.

Well, being that I am开发者_如何学编程 a beginner I wasn't thinking when I started that designing the canvas to be much larger than the screen and to allow users to scroll around to see all parts of the canvas... but alas, that's what I need to happen.

If there is an easy way to do this, please let me know.

My best guess is putting the actual creation of the canvas in a separate class which extends ScrollView and somehow just calling all the Draw()'s to that canvas from my thread. is this possible? my click events are actually captured from the main activity (just fyi).


The best option would be to use a Camera to translate the canvas. Do something like this:

// Creates a new camera object
Camera mCam = new Camera();
float startX;
float startY;

@Override
public void onTouch(MotionEvent event)
{
    if(event.getAction() == MotionEvent.ACTION_DOWN)
    {
        startX = event.getX();
        startY = event.getY();
    }
    else if(event.getAction() == MotionEvent.ACTION_MOVE)
    {
        float x = event.getX();
        float y = event.getY();

        // Lets you translate the camera by the difference
        mCam.translate(x -startX, startY - y, 0.f);
        startX = event.getX();
        startY = event.getY();
    }
}

@Override
public void onDraw(Canvas canvas)
{
    // Draw here the objects you want static in the background
    canvas.drawBitmap(mBackground, 0, 0, null);

    canvas.save();
    mCam.applyToCanvas();

    // Draw here the objects you want to move
    canvas.drawBitmap(mBall, 0, 0, null);

    canvas.restore();

    // Draw here the objects you want static on the forebround
    canvas.drawBitmap(mScore, 0, 0, null);
}

Notice that you are drawing mBall at 0,0 but due to the camera translation it will move by the amount specified. I hope this helps. Have fun :)


I slept on the problem and came up with (if i don't say so myself) A brilliant, relatively simple and elegant solution. Sorry to toot my own horn but I was literally ecstatic that i was able to come up with this.

If anyone is thinking of using this method there are a couple of conditions that made this a good choice. First, all of my objects are drawables with predefined locations using the setBounds(int,int,int,int) method, all objects also store their own coordinates for the location to draw on the canvas and all objects are called in hashmaps which allows me to call and process all the objects in existence.

Now I was thinking about what kabuko said and how it's such a waste to draw a huge canvas and how id run into click event problems, that's when I came up with this.

when a screen touch event occurs near the edge of the screen, a custom method Scroll() is called which loops through every object and adjusts the stored coordinates of the object location depending on which direction the user is trying to scroll. after it increments the objects location, it (in parallel) increments a pair of variables for x and y offset. This offset is then factored into the coordinates of the touch events so that objects can still be selected by touch regardless of the position the screen is scrolled to.

then for performance's sake a simple if statement makes it so that draw is only called on an object if that objects coordinates fall in the range of the screen.

Sorry to gloat but I really surprised and impressed myself with this, haha. I've really only been coding about a month and I almost have a fully functional 2D strategy game!

Java for dummies paid off, lol.


You could give your approach a try, even though it's not really a strategy I'd ever use myself. I suspect you're going to run into some issues with that approach anyway though. If your game already uses touch for input, you're going to have conflicts. Also, if performance is at all a concern (especially if you have any animation), you don't want go with this approach.

If you're going as far as dealing with threading, performance probably matters. Drawing is expensive, and if you make a huge canvas, you'll have to be rendering the whole thing and it will cost you. You should only draw what's on the screen (more or less). Sorry, but you'll probably need a "major overhaul"...

That said, it's really not that bad to deal with scrolling. You probably have coordinates for everything you're drawing. All you need to do is keep track of your "current coordinates" and then translate your drawing x and y by your current x and y. Dealing with the performance stuff, there's a lot you can do, but that's starting to get a bit off-topic. Take a look at these videos if you want to know more:

http://www.youtube.com/watch?v=U4Bk5rmIpic

http://www.youtube.com/watch?v=7-62tRHLcHk


The simple trick with side-scrolling games is to divide your world into tiles, where each tile has a specified amount of area.

  • Displaying a Tile Based Map
  • Scrolling a Tile Based Map
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号