在棋盘的两个方格之间拖动棋子
摘要
编写一个跳棋游戏会遇到许多挑战,在棋盘上拖动棋子就是其中之一,本期的java fun and games讨论了这个方面,并着重介绍了如何消除拖动棋子时产生的屏幕闪烁。
版权声明:任何获得matrix授权的网站,转载时请务必保留以下作者信息和链接
作者:jeff friesen;jlearner(作者的blog:http://blog.matrix.org.cn/page/jlearner)
原文:http://www.javaworld.com/javaworld/jw-08-2005/jw-0822-funandgames.html
译文:http://www.matrix.org.cn/resource/article/44/44296_checker+dragging.html
关键字:java;game
你有没有想过要编写一个跳棋游戏——可以是双人对战,也可以是人机对战?编写一个跳棋游戏会遇到许多挑战,在棋盘上把棋子从一个方格拖动到另外一个方格就是其中之一。本期的java fun and games通过一个名为checkerdrag的applet演示了棋子的拖动。
checkerdrag applet在屏幕上显示了一个棋盘和一个棋子,你可以在棋盘的边界内任意拖动棋子。checkerdrag不考虑棋子会落在哪里——也许是在不同颜色的格子上,在两个格子之间,或者是离开几个格子远。该程序的目的是演示如何拖动棋子。表1展示了applet的源代码:
表1. checkerdrag.java
// checkerdrag.java
import java.awt.*;
import java.awt.event.*;
public class checkerdrag extends java.applet.applet
{
// dimension of checkerboard square.
// 棋盘上每个小方格的尺寸
final static int squaredim = 40;
// dimension of checkerboard -- includes black outline.
// 棋盘的尺寸 – 包括黑色的轮廓线
final static int boarddim = 8 * squaredim + 2;
// dimension of checker -- 3/4 the dimension of a square.
// 棋子的尺寸 – 方格尺寸的3/4
final static int checkerdim = 3 * squaredim / 4;
// square colors are dark green or white.
// 方格的颜色为深绿色或者白色
final static color darkgreen = new color (0, 128, 0);
// dragging flag -- set to true when user presses mouse button over checker
// and cleared to false when user releases mouse button.
// 拖动标记 --当用户在棋子上按下鼠标按键时设为true,
// 释放鼠标按键时设为false
boolean indrag = false;
// left coordinate of checkerboard's upper-left corner.
// 棋盘左上角的左方向坐标
int boardx;
// top coordinate of checkerboard's upper-left corner.
//棋盘左上角的上方向坐标
int boardy;
// left coordinate of checker rectangle origin (upper-left corner).
// 棋子矩形原点(左上角)的左方向坐标
int ox;
// top coordinate of checker rectangle origin (upper-left corner).
// 棋子矩形原点(左上角)的上方向坐标
int oy;
// left displacement between mouse coordinates at time of press and checker
// rectangle origin.
// 在按键时的鼠标坐标与棋子矩形原点之间的左方向位移
int relx;
// top displacement between mouse coordinates at time of press and checker
// rectangle origin.
// 在按键时的鼠标坐标与棋子矩形原点之间的上方向位移
int rely;
// width of applet drawing area.
// applet绘图区域的宽度
int width;
// height of applet drawing area.
// applet绘图区域的高度
int height;
// image buffer.
// 图像缓冲
image imbuffer;
// graphics context associated with image buffer.
// 图像缓冲相关联的图形背景
graphics img;
public void init ()
{
// obtain the size of the applet's drawing area.
// 获取applet绘图区域的尺寸
width = getsize ().width;
height = getsize ().height;
// create image buffer.
// 创建图像缓冲
imbuffer = createimage (width, height);
// retrieve graphics context associated with image buffer.
// 取出图像缓冲相关联的图形背景
img = imbuffer.getgraphics ();
// initialize checkerboard's origin, so that board is centered.
// 初始化棋盘的原点,使棋盘在屏幕上居中
boardx = (width - boarddim) / 2 + 1;
boardy = (height - boarddim) / 2 + 1;
// initialize checker's rectangle's starting origin so that checker is
// centered in the square located in the top row and second column from
// the left.
// 初始化棋子矩形的起始原点,使得棋子在第一行左数第二列的方格里居中
ox = boardx + squaredim + (squaredim - checkerdim) / 2 + 1;
oy = boardy + (squaredim - checkerdim) / 2 + 1;
// attach a mouse listener to the applet. that listener listens for
// mouse-button press and mouse-button release events.
// 向applet添加一个用来监听鼠标按键的按下和释放事件的鼠标监听器
addmouselistener (new mouseadapter ()
{
public void mousepressed (mouseevent e)
{
// obtain mouse coordinates at time of press.
// 获取按键时的鼠标坐标
int x = e.getx ();
int y = e.gety ();
// if mouse is over draggable checker at time
// of press (i.e., contains (x, y) returns
// true), save distance between current mouse
// coordinates and draggable checker origin
// (which will always be positive) and set drag
// flag to true (to indicate drag in progress).
// 在按键时如果鼠标位于可拖动的棋子上方
// (也就是contains (x, y)返回true),则保存当前
// 鼠标坐标与棋子的原点之间的距离(始终为正值)并且
// 将拖动标志设为true(用来表明正处在拖动过程中)
if (contains (x, y))
{
relx = x - ox;
rely = y - oy;
indrag = true;
}
}
boolean contains (int x, int y)
{
// calculate center of draggable checker.
// 计算棋子的中心位置
int cox = ox + checkerdim / 2;
int coy = oy + checkerdim / 2;
// return true if (x, y) locates with bounds
// of draggable checker. checkerdim / 2 is the
// radius.
// 如果(x, y)仍处于棋子范围内则返回true
// checkerdim / 2为半径
return (cox - x) * (cox - x) +
(coy - y) * (coy - y) <
checkerdim / 2 * checkerdim / 2;
}
public void mousereleased (mouseevent e)
{
// when mouse is released, clear indrag (to
// indicate no drag in progress) if indrag is
// already set.
// 当鼠标按键被释放时,如果indrag已经为true,
// 则将其置为false(用来表明不在拖动过程中)
if (indrag)
indrag = false;
}
});
// attach a mouse motion listener to the applet. that listener listens
// for mouse drag events.
//向applet添加一个用来监听鼠标拖动事件的鼠标运动监听器
addmousemotionlistener (new mousemotionadapter ()
{
public void mousedragged (mouseevent e)
{
if (indrag)
{
// calculate draggable checker's new
// origin (the upper-left corner of
// the checker rectangle).
// 计算棋子新的原点(棋子矩形的左上角)
int tmpox = e.getx () - relx;
int tmpoy = e.gety () - rely;
// if the checker is not being moved
// (at least partly) off board,
// assign the previously calculated
// origin (tmpox, tmpoy) as the
// permanent origin (ox, oy), and
// redraw the display area (with the
// draggable checker at the new
// coordinates).
// 如果棋子(至少是棋子的一部分)没有被
// 移出棋盘,则将之前计算的原点
// (tmpox, tmpoy)赋值给永久性的原点(ox, oy),
// 并且刷新显示区域(此时的棋子已经位于新坐标上)
if (tmpox > boardx &&
tmpoy > boardy &&
tmpox + checkerdim
< boardx + boarddim &&
tmpoy + checkerdim
< boardy + boarddim)
{
ox = tmpox;
oy = tmpoy;
repaint ();
}
}
}
});
}
public void paint (graphics g)
{
// paint the checkerboard over which the checker will be dragged.
// 在棋子将要被拖动的位置上绘制棋盘
paintcheckerboard (img, boardx, boardy);
// paint the checker that will be dragged.
// 绘制即将被拖动的棋子
paintchecker (img, ox, oy);
// draw contents of image buffer.
// 绘制图像缓冲的内容
g.drawimage (imbuffer, 0, 0, this);
}
void paintchecker (graphics g, int x, int y)
{
// set checker shadow color.
// 设置棋子阴影的颜色
g.setcolor (color.black);
// paint checker shadow.
// 绘制棋子的阴影
g.filloval (x, y, checkerdim, checkerdim);
// set checker color.
// 设置棋子颜色
g.setcolor (color.red);
// paint checker.
// 绘制棋子
g.filloval (x, y, checkerdim - checkerdim / 13, checkerdim - checkerdim / 13);
}
void paintcheckerboard (graphics g, int x, int y)
{
// paint checkerboard outline.
// 绘制棋盘轮廓线
g.setcolor (color.black);
g.drawrect (x, y, 8 * squaredim + 1, 8 * squaredim + 1);
// paint checkerboard.
// 绘制棋盘
for (int row = 0; row < 8; row++)
{
g.setcolor (((row & 1) != 0) ? darkgreen : color.white);
for (int col = 0; col < 8; col++)
{
g.fillrect (x + 1 + col * squaredim, y + 1 + row * squaredim,
squaredim, squaredim);
g.setcolor ((g.getcolor () == darkgreen) ? color.white :
darkgreen);
}
}
}
// the awt invokes the update() method in response to the repaint() method
// calls that are made as a checker is dragged. the default implementation
// of this method, which is inherited from the container class, clears the
// applet's drawing area to the background color prior to calling paint().
// this clearing followed by drawing causes flicker. checkerdrag overrides
// update() to prevent the background from being cleared, which eliminates
// the flicker.
// awt调用了update()方法来响应拖动棋子时所调用的repaint()方法。该方法从
// container类继承的默认实现会在调用paint()之前,将applet的绘图区域清除
// 为背景色,这种绘制之后的清除就导致了闪烁。checkerdrag重写了update()来
// 防止背景被清除,从而消除了闪烁。
public void update (graphics g)
{
paint (g);
}
}
<applet code=checkerdrag.class width=400 height=400>
</applet>
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器