Programming Linux Games phần 10 pot

47 229 0
Programming Linux Games phần 10 pot

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

FINISHING PENGUIN WARRIOR 369 SDL_Surface *dest, int x, int y) { int row, col; SDL_Rect srcrect, destrect; Uint8 *leds; srcrect.w = disp->on_image->w; srcrect.h = disp->on_image->h; srcrect.x = 0; srcrect.y = 0; destrect = srcrect; SDL_LockSurface(disp->led_surface); leds = (Uint8 *)disp->led_surface->pixels; for (row = 0; row < disp->phys_h; row++) { for (col = 0; col < disp->phys_w; col++) { int led; destrect.x = col * disp->on_image->w + x; destrect.y = row * disp->on_image->h + y; led = leds[(row + disp->virt_y) * disp->led_surface->pitch + col + disp->virt_x]; if (led) { SDL_BlitSurface(disp->on_image, &srcrect, dest, &destrect); } else { SDL_BlitSurface(disp->off_image, &srcrect, dest, &destrect); } } } SDL_UnlockSurface(disp->led_surface); } /* Draws a 5x5 bitmapped character to the given 8-bit SDL surface. */ static void DrawChar5x5(SDL_Surface *dest, char ch, Uint8 color, int x, int y) { 370 CHAPTER 9 char *data; Uint8 *pixels; int sx, sy; data = Font5x5[(int)ch]; if (SDL_MUSTLOCK(dest)) SDL_LockSurface(dest); pixels = (Uint8 *)dest->pixels; for (sy = 0; sy < 5; sy++) { for (sx = 0; sx < 5; sx++) { if (data[5*sy+sx] != ’ ’) { pixels[dest->pitch*(y+sy)+x+sx] = color; } else { pixels[dest->pitch*(y+sy)+x+sx] = 0; } } } SDL_UnlockSurface(dest); } /* ===================================== End of LED stuff. Back to the world of Penguin Warrior. ===================================== */ /* A temporary buffer for the characters currently on the display. */ #define SCROLLER_BUF_SIZE 10 char scroller_buf[SCROLLER_BUF_SIZE]; /* Message to scroll. This can be changed. */ const char *scroller_msg = "Welcome to Penguin Warrior"; int scroller_pos = 0; int scroller_ticks = 0; /* Various LED displays that appear on the Penguin Warrior screen. */ LED_Display player_score, player_shields, player_charge; LED_Display opponent_score, opponent_shields; LED_Display status_msg; FINISHING PENGUIN WARRIOR 371 int InitStatusDisplay(void) { if (LED_CreateDisplay(&player_score, 12, 5, 12, 5, "led-red-on.bmp", "led-red-off.bmp") < 0) return -1; if (LED_CreateDisplay(&player_shields, 12, 1, 12, 1, "led-red-on.bmp", "led-red-off.bmp") < 0) return -1; if (LED_CreateDisplay(&player_charge, 80, 1, 80, 1, "led-red-on.bmp", "led-red-off.bmp") < 0) return -1; if (LED_CreateDisplay(&opponent_score, 12, 5, 12, 5, "led-red-on.bmp", "led-red-off.bmp") < 0) return -1; if (LED_CreateDisplay(&opponent_shields, 12, 1, 12, 1, "led-red-on.bmp", "led-red-off.bmp") < 0) return -1; if (LED_CreateDisplay(&status_msg, 56, 5, 66, 5, "led-green-on.bmp", "led-green-off.bmp") < 0) return -1; memset(scroller_buf, 0, SCROLLER_BUF_SIZE); return 0; } void CleanupStatusDisplay(void) { LED_FreeDisplay(&player_score); LED_FreeDisplay(&player_shields); LED_FreeDisplay(&player_charge); LED_FreeDisplay(&opponent_score); LED_FreeDisplay(&opponent_shields); LED_FreeDisplay(&status_msg); } void SetStatusMessage(const char *msg) 372 CHAPTER 9 { scroller_pos = 0; scroller_msg = msg; } void SetPlayerStatusInfo(int score, int shields, int charge) { char buf[3]; Uint8 *pixels; int i; /* Set the score counter. */ sprintf(buf, "%2i", score); DrawChar5x5(player_score.led_surface, buf[0], 1, 0, 0); DrawChar5x5(player_score.led_surface, buf[1], 1, 6, 0); /* Set the shield bar. */ SDL_LockSurface(player_shields.led_surface); pixels = (Uint8 *)player_shields.led_surface->pixels; for (i = 0; i < 12; i++) { if (i < shields * 12 / 100) pixels[i] = 1; else pixels[i] = 0; } SDL_UnlockSurface(player_shields.led_surface); /* Set the phaser charge bar. */ SDL_LockSurface(player_charge.led_surface); pixels = (Uint8 *)player_charge.led_surface->pixels; for (i = 0; i < 80; i++) { if (i < charge * 80 / PHASER_CHARGE_MAX) pixels[i] = 1; else pixels[i] = 0; } SDL_UnlockSurface(player_charge.led_surface); } void SetOpponentStatusInfo(int score, int shields) FINISHING PENGUIN WARRIOR 373 { char buf[3]; Uint8 *pixels; int i; /* Set the score counter. */ sprintf(buf, "%2i", score); DrawChar5x5(opponent_score.led_surface, buf[0], 1, 0, 0); DrawChar5x5(opponent_score.led_surface, buf[1], 1, 6, 0); /* Set the shield bar. */ SDL_LockSurface(opponent_shields.led_surface); pixels = (Uint8 *)opponent_shields.led_surface->pixels; for (i = 0; i < 12; i++) { if (i < shields * 12 / 100) pixels[i] = 1; else pixels[i] = 0; } SDL_UnlockSurface(opponent_shields.led_surface); } void UpdateStatusDisplay(SDL_Surface *screen) { int i; /* Update the scroller. This is not linked to the global time_scale, since speed really doesn’t matter. The only effect of a high framerate would be that the scrolling message would move faster. */ if ((scroller_ticks % 6) == 0) { char ch; for (i = 0; i < SCROLLER_BUF_SIZE-1; i++) { scroller_buf[i] = scroller_buf[i+1]; } if (scroller_msg[scroller_pos] == ’\0’) { ch = ’ ’; scroller_pos ; } else { ch = scroller_msg[scroller_pos]; } 374 CHAPTER 9 scroller_pos++; scroller_buf[i] = ch; status_msg.virt_x = 0; for (i = 0; i < SCROLLER_BUF_SIZE; i++) { DrawChar5x5(status_msg.led_surface, scroller_buf[i], 1, 6 * i, 0); } } else { status_msg.virt_x++; } scroller_ticks++; LED_DrawDisplay(&player_score, screen, 0, 0); LED_DrawDisplay(&player_shields, screen, 0, 48); LED_DrawDisplay(&player_charge, screen, 0, 471); LED_DrawDisplay(&opponent_score, screen, 544, 0); LED_DrawDisplay(&opponent_shields, screen, 544, 48); LED_DrawDisplay(&status_msg, screen, 96, 0); } status.c is divided into two parts. The first part implements the LED simulator described earlier, and the second part uses the simulator to create game status displays for Penguin Warrior. Penguin Warrior’s status display consists of six pieces: a scoreboard and shield block for each player, a scrolling message banner, and a phaser charge readout for the local player. Each piece has its own LED Display structure. To use the status display system, the game engine calls InitStatusDisplay at startup and then executes UpdateStatusDisplay during each frame. Whenever a game statistic (score, shield level, or phaser charge) changes, the game calls SetPlayerStatusInfo or SetOpponentStatusInfo to update the information. It can set new banner messages with SetStatusMessage. The LED simulator redraws the boards at each frame. Although alpha-blended blits are relatively slow, this update is negligible in comparison to the rest of the game loop. Figure 9–3 shows the new status display system. Penguin Warrior is complete, at long last! It’s a relatively small game, but it contains all of the major ingredients you’d find in a larger production, and the engine performs reasonably well. The next section discusses some of the things I FINISHING PENGUIN WARRIOR 375 Figure 9–3: Penguin Warrior’s status display could have done differently throughout the project. In Retrospect I created Penguin Warrior to demonstrate game programming in the Linux environment. I started writing it while I was trying to decide where to go with Chapter 4, and I’ve added features throughout the book to demonstrate various topics that came up. There was no formal design process, other than the planning that went into the book as a whole. Penguin Warrior turned out well enough, but it’s an incredibly simple game compared to most. At the risk of hypocrisy, I strongly recommend that you put considerable thought into the design of your games. It’s easy to write games that look good; it’s much harder to write games that play well. Admittedly, Penguin Warrior doesn’t have much depth. 376 CHAPTER 9 What could I have done differently? Here are a few things that come to mind. • I could have used C++ instead of C. C++ lends itself well to game programming, since games usually simulate interactions between physical objects to some extent. In fact, any object-oriented programming language would be beneficial in that regard. There are plenty of arguments for and against C++, and it’s the topic of many mailing list holy wars. • Penguin Warrior would benefit from a more sophisticated networking system. The current TCP-based system, in which the clients take turns exchanging packets, is simple, but its performance is highly dependent upon the quality of the underlying network. A UDP-based protocol would be more complex to implement, but it could potentially offer better performance. • In hindsight, Tcl was not an especially good choice for the scripting engine. It works in this case, but it’s not a very good solution for number crunching or managing large amounts of data. If I were to rewrite Chapter 6, I would probably choose a Lisp variant such as Scheme. • Resource management is always a challenge. The present implementation of Penguin Warrior uses an ad hoc resource-loading routine, but this task could be performed in a more general and flexible way. Each resource (a sound clip or a graphic) could have a symbolic name, and the resource manager could load them on demand. • The source tree would be much easier to build if it had a GNU Autoconf script. As it stands, you usually need to tweak the makefile to build the game. While this is fine for developers, it might be confusing for end users. There are also some gameplay features that would make nice additions to Penguin Warrior (and perhaps good weekend projects for interested readers): • More weapons. Many games allow the player to pick up “power-ups” from the playing field. Perhaps Penguin Warrior could have floating Power Penguins for the players to find. • A radar screen for tracking the opponent. Alpha blending could add a nice effect to such a display. FINISHING PENGUIN WARRIOR 377 • The ability to have two scripted opponents play each other over the network. This would be useless but fun to watch. That’s it for Penguin Warrior. The next chapter talks about the various Linux distributions and package managers you have to contend with, as well as FreeBSD portability. It also discusses the Loki Setup tool, a program for installing games in a distribution-independent way. [...]... available to your users TO EVERY MAN A LINUX DISTRIBUTION 383 Linux Isn’t Alone: Supporting FreeBSD Linux isn’t the only contender in the free OS arena.6 FreeBSD is a very similar system with an active and knowledgeable user community Although FreeBSD can theoretically run Linux binaries out of the box, a few differences sometimes prevent Linux applications (and games) from working Aside from these minor... documentation for the XML script format 9 http://www.lokigames.com TO EVERY MAN A LINUX DISTRIBUTION 393 Understanding the Linux Filesystem Standard Linux evolved from Linus Torvald’s pet project into a full-blown multiuser operating system, and its filesystem has gone through a long period of evolution A while back people decided that it wouldn’t do for each Linux distribution to use a different filesystem, and... your program depends on proc/, you’ll probably have to do some porting 6 Although I speak of Linux here as a complete operating system, the more correct term would be Linux- based system,” or as the Free Software Foundation would prefer, Linux- based GNU system.” FreeBSD is the whole shabang—that is, unlike Linux, FreeBSD encompasses a complete operating system, including a kernel and a set of software... user This concludes our discussion of installing software under Linux In the next chapter we’ll talk about Wait, there are no more chapters! We’ve thoroughly scratched the surface of game programming with Linux There’s a lot we haven’t covered, but hopefully you’ve now seen enough that you can pick up the rest on your own Whether or not Linux will become a major gaming platform is anyone’s guess, but... Whatever you decide to do, you’d be well advised to respect the Linux filesystem standard and account for the differences between various Linux distributions If you don’t, you’ll irritate users at the very least and possibly cause serious problems On the brighter side, a well-packaged program can make a good first impression 380 CHAPTER 10 Source or Binary? The first decision you’ll have to make is whether... code is probably the easiest way to distribute a Linux application or game, and this is perfectly acceptable in some cases (especially if the project takes advantage of Autoconf) However, source tarballs have several disadvantages: TO EVERY MAN A LINUX DISTRIBUTION 385 • Although they’re developer-friendly, source tarballs aren’t exactly newbie-friendly New Linux users often aren’t comfortable with building... and other reasons, many Linux developers make precompiled packages of their software available Each Linux distribution has its own idea of what exactly constitutes a “package,” and so developers often choose just one or two major distributions to support The two most commonly supported package types are Red Hat’s RPM and Debian’s DEB Neither of these are specific to their “parent” Linux distributions;... commonly supported package types are Red Hat’s RPM and Debian’s DEB Neither of these are specific to their “parent” Linux distributions; SuSE, Caldera, and TurboLinux are RPM-based, and Debian’s packaging system has found its way into Corel Linux and Storm Linux (which are actually Debian offshoots) Package systems provide a bit of extra functionality over source tarballs Package managers can usually install... like Autoconf, it’s worth learning if you intend to maintain complicated Linux software packages Debian packages are even a bit trickier to 386 CHAPTER 10 roll than RPMs, but they are explained in detail on the Debian project’s developer Web site7 Making Slackware Packages Unlike RPM and Debian packages, packages for Slackware Linux are quite easy to create To make a Slackware package, install your... graphics cards Since Linux OpenGL support is changing rapidly, it’s a good idea to include a working copy of the appropriate drivers with any packaged game, in case the next release of the drivers doesn’t work correctly (3D graphics support under Linux is expected to stabilize a bit in the near future as the DRI becomes the new standard, but now is a rough time for 3D graphics in Linux. ) Next is the . specific to their “parent” Linux distributions; SuSE, Caldera, and TurboLinux are RPM-based, and Debian’s packaging system has found its way into Corel Linux and Storm Linux (which are actually. C. C++ lends itself well to game programming, since games usually simulate interactions between physical objects to some extent. In fact, any object-oriented programming language would be beneficial. for installing games in a distribution-independent way. Chapter 10 To Every Man a Linux Distribution You’ve probably noticed that there are a lot of Linux distributions floating around the Internet. Some

Ngày đăng: 06/08/2014, 09:20

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan