In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-03 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
Editor to share with you how to use the Game API function to make two-dimensional action games, I believe that most people do not know much about it, so share this article for your reference, I hope you can learn a lot after reading this article, let's go to know it!
MIDP 2.0 includes an API function to simplify writing two-dimensional games. This API function is very simple and includes only five classes in the javax.microedition.lcdui.game package. These five classes mainly provide two important functions:
's new GameCanvas class makes it possible to draw a screen in a game loop and respond to keyboard input without calling the system's paint and input threads.
's powerful and complex layer (layer) API function can easily and efficiently build complex scenes.
Screen.width-333) this.width=screen.width-333; ">
MuTank Example
Create a game loop (game loop) using the GameCanvas class
The GameCanvas class is a Canvas class with additional functionality that provides a way to immediately redraw and check the keystroke status of a device. These new methods encapsulate all functions (functions) of a game in a loop and are controlled by a single thread. Why is this so attractive? Let's first consider how you execute a typical game that uses the Canvas class:
Public void MicroTankCanvas
Extends Canvas
Implements Runnable {
Public void run () {
While (true) {
/ / Update the game state.
Repaint ()
/ / Delay one time step.
}
}
Public void paint (Graphics g) {
/ / Painting code goes here.
}
Protected void keyPressed (int keyCode) {
/ / Respond to key presses here.
}
}
This is not a beautiful picture. The run () method, which runs in the application thread, refreshes the game at each time period. A typical task is to refresh the position of a ball or flying object and animate a character or aircraft. Each time through the loop body, the repaint () method is used to refresh the screen. The system sends the keystroke event to KeyPressed (), which refreshes the game state appropriately.
The problem is that everything is in a different thread, and it is easy to confuse the game code in the above three different ways. When the active drawing loop body in the run () method calls the repaint () method, there is no way to know exactly when the system will call the paint () method. When the system calls KeyPressed (), there is no way to know what another part of the program is doing. If the code in your KeyPressed () is about to refresh the state of the game, and the paint () method will display the screen at the same time, the screen will continue to behave in a very strange state. If it takes more than a single time period to show the screen, the animation will look bumpy or strange.
The GameCanvas class allows you to avoid the common drawing (painting) and key message (key-event) mechanisms, so all game logic can be included in a single loop. First, the GameCanva class allows you to access Graphics objects directly using the getGraphics () method. Any rendering of the returned Graphics object can be achieved through an off-screen buffer (offscreen buffer). You can use flushGraphics () to copy the buffer to the screen and will not return until the screen is refreshed. This approach gives you more control than calling the repaint () method. The Repaint () method returns a value immediately, so that your application is not sure when the system will call paint () to refresh the screen.
The GameCanvas class also contains a method used to obtain the current state of device keys, known as polling technology. You can immediately determine which key is pressed by calling the getKeyStates () method of the GameCanvas class, instead of waiting for the system to call the KeyPressed () method.
Here is a typical game loop body that uses the GameCanvas class:
Public void MicroTankCanvas
Extends GameCanvas
Implements Runnable {
Public void run () {
Graphics g = getGraphics ()
While (true) {
/ / Update the game state.
Int keyState = getKeyStates ()
/ / Respond to key presses here.
/ / Painting code goes here.
FlushGraphics ()
/ / Delay one time step.
}
}
}
The following example describes a basic game loop body. It shows you a rotating "X" that you can use the arrow keys to move around the screen. The Run () method here is particularly skinny, thanks to GameCanvas.
Import javax.microedition.lcdui.*
Import javax.microedition.lcdui.game.*
Public class SimpleGameCanvas
Extends GameCanvas
Implements Runnable {
Private boolean mTrucking
Private long mFrameDelay
Private int mX, mY
Private int mState
Public SimpleGameCanvas () {
Super (true)
MX = getWidth () / 2
MY = getHeight () / 2
MState = 0
MFrameDelay = 20
}
Public void start () {
MTrucking = true
Thread t = new Thread (this)
T.start ()
}
Public void stop () {mTrucking = false;}
Public void run () {
Graphics g = getGraphics ()
While (mTrucking = = true) {
Tick ()
Input ()
Render (g)
Try {Thread.sleep (mFrameDelay);}
Catch (InterruptedException ie) {}
}
}
Private void tick () {
MState = (mState + 1) 20
}
Private void input () {
Int keyStates = getKeyStates ()
If ((keyStates & LEFT_PRESSED)! = 0)
MX = Math.max (0, mX-1)
If ((keyStates & RIGHT_PRESSED)! = 0)
MX = Math.min (getWidth (), mX + 1)
If ((keyStates & UP_PRESSED)! = 0)
MY = Math.max (0, mY-1)
If ((keyStates & DOWN_PRESSED)! = 0)
MY = Math.min (getHeight (), mY + 1)
}
Private void render (Graphics g) {
G.setColor (0xffffff)
G.fillRect (0,0, getWidth (), getHeight ())
G.setColor (0x0000ff)
G.drawLine (mX, mY, mX-10 + mState, mY-10)
G.drawLine (mX, mY, mX + 10, mY-10 + mState)
G.drawLine (mX, mY, mX + 10-mState, mY + 10)
G.drawLine (mX, mY, mX-10, mY + 10-mState)
FlushGraphics ()
}
}
The code for the example given in this article includes a MIDlet that uses this canvas. You can try running SimpleGameMIDlet on Mini Program and see how it works. You will see something like a starfish doing aerobics (maybe it is looking for its lost leg).
Screen.width-333) this.width=screen.width-333; ">
SimpleGameMIDlet Screen Shot
The game scene is like an onion (layered)
A typical two-dimensional action game often contains a background and several animated characters. Although you can draw this scene yourself, the Game API function allows you to use layers to create the scene. You can make a background layer for a city and another layer that contains a car. Put the car layer on the background and you create a complete scene. By putting the car on a separate layer, you can easily manipulate it without being affected by the background and other layers.
The Game API function uses the following four classes to provide flexible support for layers
The Layer class is the abstract base class for all layer class objects. It defines the basic properties of a layer, including location, size, and whether the layer is visible. Each subclass of the Layer class must define a paint () method to represent the layer on an image that will be drawn to the surface of the screen. Two exact subclasses, TiledLayer and Sprite, should meet the needs of your two-dimensional game.
The TiledLayer class is used to create a background image. You can use a small collection of source images to efficiently create large images.
The Sprite class is an animation layer. If you provide the source frame, you can have complete control over the entire animation. The Sprite class also provides mirroring and 90-degree rotation of the source frame.
The LayerManager class is a very useful class that saves the action tracks of all layers in your scene. A simple call to the paint () method of the LayerManager class is sufficient to control all the layers contained.
Use the TiledLayer class
Although it contains some subtle differences that are not obvious, the TiledLayer class is easy to understand. The basic idea of this class is to use a source image to provide a set of image patches that can be combined into a large scene. For example, the following image is 6448 pixels.
Screen.width-333) this.width=screen.width-333; ">
Source Image
The image is divided into 12 16-16 image patches. The TiledLayer class assigns each image patch number, the image in the upper left corner is specified as 1, and so on. The patches of the above source image are numbered as follows:
Screen.width-333) this.width=screen.width-333; ">
Tile Numbering
It is very simple to create a TiledLayer class in code. You need to determine the number of rows and columns, the source image, and the pixel size of each patch in the source image. The following code snippet shows you how to load the image and create the TiledLayer class.
Image image = Image.createImage ("/ board.png")
TiledLayer tiledLayer = new TiledLayer (10, 10, image, 16, 16)
In the example, the new TiledLayer class has 10 rows and 10 columns. The size of these image patches from image is 16 to 16 pixels.
The interesting part is to use these image patches to create a scene. An image patch can be assigned to an array cell using the setCell () method. You need to provide the number of rows and rows of this array of cells and the number of the image patch. For example, you can assign the image patch numbered 5 to the third array cell in line 2 by calling the setCelll (2Power1) method. If you think these parameters don't look right, please note that the image patch number starts at 1, while the row and column numbers start at 0. By default, all array cells in the new TiledLayer class object have image patch labels of 0, which means they are empty.
The following code snippet shows you a way to populate TiledLayer class objects with an array of integers. In the actual image, the TiledLayer class can be defined from the resource file, which allows more flexibility in defining the background and provides new backgrounds and levels to enhance the playability of the game.
Private TiledLayer createBoard () {
Image image = null
Try {image = Image.createImage ("/ board.png");}
Catch (IOException ioe) {return null;}
TiledLayer tiledLayer = new TiledLayer (10, 10, image, 16, 16)
Int [] map = {
1, 1, 1, 1, 11, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 9, 0, 0, 0, 0, 0
0, 0, 0, 0, 1, 0, 0, 0, 0, 0
0, 0, 0, 7, 1, 0, 0, 0, 0, 0
1, 1, 1, 1, 6, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 7, 11, 0
0, 0, 0, 0, 0, 0, 7, 6, 0, 0
0, 0, 0, 0, 0, 7, 6, 0, 0, 0
}
For (int I = 0; I < map.length; iTunes +) {
Int column = I% 10
Int row = (I-column) / 10
TiledLayer.setCell (column, row, map [I])
}
Return tiledLayer
}
To display the TiledLayer class object on the screen, you need to call the paint () method of a Graphics object.
The TiledLayer class also supports animated image posts, which makes it easy to move a collection of cells through a series of tiles. For a more detailed explanation, refer to the API documentation related to the TiledLayer class.
Using Sprite Class to realize character Animation
Another concrete Layer class provided in the Game API function is the Sprite class. On the one hand, the Sprite class is a conceptual reversal of the TileLayer class. The TiledLayer class uses a palette of source image patches to create a large scene, while the Sprite class uses a series of source image frames to produce animation.
All you need to create a Sprite class is the source image and the size of each frame. In the TiledLayer class, the source image is divided into image patches of the same size; in the Sprite class, sub-images are called frames. In the following example, the source image tank.png is used to create a Sprite class object with a frame size of 32 pixels.
Private MicroTankSprite createTank () {
Image image = null
Try {image = Image.createImage ("/ tank.png");}
Catch (IOException ioe) {return null;}
Return new MicroTankSprite (image, 32, 32)
}
Each frame in the source image has a number, starting with 0, to accumulate. (don't be confused here, remember that the number of image patches starts at 1.) the Sprite class has a sequence of frames that determines the order in which frames are displayed. The default frame sequence for a new Sprite class object simply accumulates from 0 according to the available frames.
Using the nextFrame () and prevFrame () methods of the Sprite class, you can move frames forward or backward in a sequence of frames. These methods connect the beginning and end of the frame sequence. For example, if the Sprite class object has already displayed the frame at the end of the frame sequence, calling the nextFrame () method will display the first frame of the frame sequence.
By calling the setFrameSequence () method, you can determine the sequence of frames that is different from the default by the sequence specified by the integer array.
You can also call the setFrame () method to jump to a frame in the current frame sequence. You can't jump to a specific frame number, you can only jump to a specific point in the frame sequence.
When using the paint () method inherited from the Layer class, the frame change is realized only when the Sprite class is represented in the next time period.
The Sprite class can also transform the source frame. You can rotate the frame 90 degrees, or mirror it, or both. The constants in the Sprite class enumerate these possibilities. The current transformation of the Sprite class can be set by passing one of these constants to the setTransform () method. The following example shows the current frame mirrored around the vertical center and rotated 90 degrees:
/ / Sprite sprite =.
Sprite.setTransform (Sprite.TRANS_MIRROR_ROT90)
The transformation is applied so that the reference pixels of the Sprite class do not move. By default, the reference pixel of the Sprite class is located at the (0mem0) point in the Sprite class coordinate system, that is, the upper-left corner. When the transformation mode is applied, the position of the reference pixel is also changed. The Sprite class is repositioned so that the reference pixel is still in its original position.
You can change the location of the reference pixel by calling the defineReferencePixel () method. For most types of animation, you can define the reference pixel at the center of the sprite.
Finally, the Sprite class provides several collidesWith () methods to detect collisions with other Sprites,ItledLayers, or Images class objects. You can use the detection rectangle (fast but rough) or pixel level (slow but accurate) to detect collisions. The subtle differences in these methods are hard to describe; for details, refer to the API documentation.
MuTank example
The MuTank example shows you the use of the TiledLayer,Sprite and LayerManager classes.
The most important classes are the MicroTankCanvas class that contains most of the code and the MicroTankSprite class that encapsulates tank behavior.
The MicroTankSprite class makes a large number of transformations. It uses a source image with only 3 frames to display tanks pointing in 16 directions. The two common methods Turn () and forward () make the tank easy to control.
The MicroTankCanvas class, a subclass of the GameCanvas class, contains an animation loop body that you should be familiar with in the run () method. The tick () method is used to detect whether the tank has touched the partition. If it does, call the undo () method of the MicroTankCanvas class to reverse its most recent motion. The Input () method simply detects whether the button is pressed and adjusts the direction or position of the tank at the same time. The Render () method uses a LayerManager class object to process the painting. The LayerManager class contains two layers, the tank layer and the partition layer.
The Debug () method called from the game loop body is used to compare the time taken to pass through the game loop body with the expected cycle time (80 milliseconds) and to display the percentage of time on the screen. It is for debugging and diagnostic purposes only and will be deleted before the game is sent to the user.
The timing of the game loop body is more complex than the previous SimpleGameCanvas class. To more accurately repeat the game loop body every 80 milliseconds, the MicroTankCanvas class measures the time spent by the tick (), input (), and render () methods. Then stop and spend the rest of the 80 milliseconds so that the total time spent through each cycle is as close to 80 milliseconds as possible.
The above is all the contents of the article "how to use Game API functions to make two-dimensional action games". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.