下面通过一个代码案例来制作一个这样的小游戏。游戏的GUI部分使用了JAVAFX来编写,下面是代码部分和效果图展示,话不多说直接上代码,供参考和学习。
二、代码部分
public class FXController extends Application implements Serializable{
private static final long serialVersionUID = 1L;
private double x=0,y=0,width = 500,height = 800,jianju=18;
private volatile int img_x = -1,img_y = -1,
end_x = 50,end_y = 625,
count = 0,status = 0,
guanqia = 4,qiehuan_x = (int) (width*2);
private volatile boolean qiehuan = false,setting_show = false,play_muisc = false,
last = false;
private Canvas canvas = new Canvas(width,height);
private GraphicsContext context = canvas.getGraphicsContext2D();
private Random random = new Random();
private ExecutorService service = new ThreadPoolExecutor(10, 100, 0, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(100));
private Font font = Font.font("微软雅黑",FontWeight.BOLD,60);
//private Font wei = Font.font("微软雅黑",FontWeight.BOLD,40);
private AudioClip clip = play_music("D:\\桌面\\imagess\\button.mp3",1,false),clip2,
clip3 = play_music("D:\\桌面\\imagess\\xiaochu2.mp3",1,false);
private static List<Image> back,yuansu,buttons,icon,huiyuansu,bu,jie,setting;
private static Map<String,String> muisc;
private List<ImageInfo> info1 = new ArrayList<ImageInfo>(8);
private ImageInfo[][] images = new ImageInfo[guanqia][guanqia];
private ImageInfo[][] images2 = new ImageInfo[guanqia][guanqia];
private boolean[] muisc_is = new boolean[3];
@AllArgsConstructor
//@ToString
private static final class ImageInfo{
private double x,y,value,index;
private boolean show;
}
static{
try {
Path[] paths=Files.list(Paths.get("D:\\桌面\\imagess")).toArray(Path[]::new);
Map<String, List<Image>> maps =Stream.of(paths)
.filter(image->image.getFileName().toString().matches(".+\\.(?i)(jpg|png)"))
.sorted(Comparator.comparing(path->{
String filename = path.getFileName().toString();
return filename.startsWith("bu_")?
Integer.parseInt(filename.replaceAll("[^\\d+]","")):0;
})).collect(Collectors.groupingBy(path->{
String string = path.getFileName().toString();
return string.startsWith("1_")?"yuansu":string.matches("\\d+\\.png")?"buttons":
string.matches("(01|02)\\.jpg")?"back":string.startsWith("setting")?"setting":
string.startsWith("jie_")?"jie":string.startsWith("bu_")?"bu":"icon";
},Collectors.mapping(path->new Image(path.toUri().toString()),Collectors.toList())));
muisc = Stream.of(paths).filter(path->path.getFileName().toString().matches(".+\\.(?i)(mp3|wav)"))
.collect(Collectors.toMap(k->k.getFileName().toString().split("\\.")[0],v->v.toString()));
back = maps.get("back");
yuansu = maps.get("yuansu");
huiyuansu = yuansu.stream().map(m->pixWithImage(3,m)).collect(Collectors.toList());
buttons = maps.get("buttons");
icon = maps.get("icon");
bu = maps.get("bu");
jie = maps.get("jie");
setting = maps.get("setting");
} catch (IOException e) {
e.printStackTrace();
throw new Error("ERR");
}
}
private void random(){
try {
AudioClip clip = play_music(muisc.get("xipai"),-1,true);
clip.setVolume(1.0);
int index = 0;
List<Integer> ints1 = random_next_int(images.length*images[0].length,yuansu.size());
List<Integer> ints2 = random_next_int(images2.length*images2[0].length,yuansu.size());
count = ints1.size()+ints2.size();
for (int i = 0; i < images.length; i++)
for (int j = 0; j < images[i].length; j++){
TimeUnit.MILLISECONDS.sleep(50);
double width1 = 50,height1 = 50,x = (width-images.length*width1+i*jianju)/2+width1*i,y = (guanqia>4?100:200)+height1*j+j*jianju;
if(index<ints1.size())images[i][j] = new ImageInfo(x,y,ints1.get(index++),1,true);
}index = 0;
for (int i = 0; i < images2.length; i++)
for (int j = 0; j < images2[i].length; j++){
TimeUnit.MILLISECONDS.sleep(50);
double width1 = 50,height1 = 50,x = (width-images2.length*width1+i*jianju)/2+width1*i,y = (guanqia>4?100:200)+height1*j+j*jianju;
if(index<ints2.size())images2[i][j] = new ImageInfo(x,y,ints2.get(index++),2,true);
}
clip.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
private AudioClip play_music(String path,Integer count,Boolean auto){
AudioClip clip = new AudioClip(Paths.get(path).toUri().toASCIIString());
clip.setCycleCount(count);
if(auto)clip.play();
return clip;
}
private Bounds getFontWH(String text,Font font){
Text texts = new Text(text);texts.setFont(font);
return texts.getBoundsInLocal();
}
private void rest(int length){
guanqia = length>0?length:guanqia+1;
images = new ImageInfo[guanqia][guanqia];
images2 = new ImageInfo[guanqia][guanqia];
service.execute(()->random());
info1.clear();
end_x = 50;
}
private double[] dengbi(Image img,Double new_width){
boolean is_bili = false;
double bili = (is_bili = new_width<img.getWidth())?new_width/img.getWidth():img.getWidth()/new_width;
return new double[]{new_width,is_bili?img.getHeight()*bili:img.getHeight()/bili};
}
public FXController(){
canvas.setCache(true);
clip2 = play_music(muisc.get("bgm"),-1,true);
service.execute(()->{
try {
while(true){
TimeUnit.MICROSECONDS.sleep(100);
if(qiehuan && qiehuan_x--<-(width+275)){qiehuan_x = (int) (width*2);qiehuan = false;status = 4;rest(0);}
if(img_x ==-1 && img_y ==-1)continue;
ImageInfo[][] images = !this.images[img_x][img_y].show?this.images2:this.images;
images[img_x][img_y].x=images[img_x][img_y].x>end_x?images[img_x][img_y].x-3:images[img_x][img_y].x+3;
images[img_x][img_y].y+=3;
if(images[img_x][img_y].y >= end_y){
end_x+=50;images[img_x][img_y].show=false;
info1.add(new ImageInfo(images[img_x][img_y].x,images[img_x][img_y].y,images[img_x][img_y].value,images[img_x][img_y].index,images[img_x][img_y].show));
img_x = img_y = -1;
ImageInfo[] info2 = new ImageInfo[3];
AtomicInteger integer = new AtomicInteger(0);
boolean falses = IntStream.range(0,info1.size())
.anyMatch(index->{
if(index<info1.size()-1){
ImageInfo info_1 = info1.get(index);
ImageInfo info_2 = info1.get(index+1);
if(info_1.value==info_2.value){
info2[integer.get()] = info_1;
info2[integer.get()+1] = info_2;
if(integer.incrementAndGet()==2)return true;
}else integer.set(0);
}
return false;
});
if(falses){
count-=3;end_x-=50*3;
TimeUnit.MILLISECONDS.sleep(200);
if(!play_muisc)clip3.play();
info1.removeAll(Arrays.asList(info2));
if(count<=0){
TimeUnit.MILLISECONDS.sleep(500);
status=3;//play_music(muisc.get("success"),1,true);
}
}if(info1.size()>=8){TimeUnit.MILLISECONDS.sleep(500);
play_music(muisc.get("false"),1,true);
status=1;}
// info1.stream().collect(Collectors.groupingBy(info->info.value))
// .entrySet().stream().filter(info->info.getValue().size()==3)
// .findFirst().ifPresent(info->{
// end_x-=50*3;
// try {
// TimeUnit.MILLISECONDS.sleep(150);
// clip.play();
// info1.removeAll(info.getValue());
// } catch (Exception e) {
// e.printStackTrace();
// }
// });
}
}
} catch (Exception e) {
e.printStackTrace();
}
});
service.execute(()->{
try {
int index = 0,index3 = 0,back_image = 0,jie_image = 0;
while(true){
TimeUnit.MILLISECONDS.sleep(100);
context.clearRect(0,0,canvas.getWidth()+1,canvas.getHeight()+1);
boolean disable = String.valueOf(status).matches("[123]");
if(status==0){
//画首页背景动画
if(index3++%5==0){
if(++jie_image>=back.size())jie_image = 0;
context.drawImage(jie.get(jie_image),0,0,width,height);
if(index>=10)index = 0;
}else context.drawImage(jie.get(jie_image),0,0,width,height);
//画顶部按钮
for (int j = 4; j < 7; j++) {
if(!last && j>5)continue;
Image image = (last && j>5)?bu.get(7):bu.get(j);
double width1 = 50,x = j>4?width-width1-30:30,y = j>5?90:30;
if(!setting_show && new Rectangle2D(x,y,width1,width1).intersects(this.x,this.y,1,1)){
this.x=this.y=0;width1+=10;
if(!play_muisc)clip.play();
if(j==4)System.exit(0);
else if(j==5)setting_show = true;
else status=4;
}context.drawImage(image,x,y,width1,width1);
}
//画主界面按钮
for (int j = 0;j < 3;j++) {
Image image = bu.get(j);
double[] wh = dengbi(image,200D);
double x = (width-wh[0])/2,y = 310+wh[1]*j+j*30;
if(!setting_show && new Rectangle2D(x, y,wh[0],wh[1]).intersects(this.x,this.y,1,1)){
this.x=this.y=0;wh[0]+=10;wh[1]+=10;
if(!play_muisc)clip.play();
status=4;rest(4+j);
}context.drawImage(image,x,y,wh[0],wh[1]);
}
if(setting_show){
context.setFill(Color.BLACK);
context.setGlobalAlpha(0.4);
context.fillRect(0,0,width,height);
context.setGlobalAlpha(1.0);
Image image = setting.get(0);
Image image2 = bu.get(3);
double[] wh = dengbi(image,300D);
double[] wh2 = dengbi(image2,140D);
context.drawImage(image,(width-wh[0])/2,(height-wh[1])/2,wh[0],wh[1]);
if(new Rectangle2D((width-wh2[0])/2,510,wh2[0],wh2[1]).intersects(this.x,this.y,1,1)){
this.x=this.y=0;wh2[0]+=10;wh2[1]+=10;
if(!play_muisc)clip.play();setting_show = false;
}context.drawImage(image2,(width-wh2[0])/2,510,wh2[0],wh2[1]);
for (int j = 0;j < 3;j++) {
double width1 = 50,x1 = 160,y1 = 290+j*width1+j*30;
if(new Rectangle2D(x1,y1,width1,width1).intersects(this.x,this.y,1,1)){
this.x=this.y=0;width1+=10;if(!play_muisc)clip.play();
if(j==0){
muisc_is[j] = !muisc_is[j];
if(muisc_is[j])clip2.stop();else clip2.play();
}else if(j==1)
muisc_is[j] = play_muisc = !muisc_is[j];
else muisc_is[j] = play_muisc = !muisc_is[j];
}context.drawImage(muisc_is[j]?bu.get(8):bu.get(9),x1,y1,width1,width1);
}}
continue;
}
//-------------------------------------------------------------------------------------------------------
//画背景图片
if(index++%10==0){
if(++back_image>=back.size())back_image = 0;
context.drawImage(back.get(back_image),0,0,width,height);
if(index>=10)index = 0;
}else context.drawImage(back.get(back_image),0,0,width,height);
//画顶部按钮
Image image0 = bu.get(6);
double width0 = 50,x0 = 30,y0 = 30;
if(!setting_show && new Rectangle2D(x0,y0,width0,width0).intersects(this.x,this.y,1,1)){
this.x=this.y=0;width0+=10;if(!play_muisc)clip.play();
status = 0;last = true;
}context.drawImage(image0,x0,y0,width0,width0);
//画第二层元素
for (int i = 0; i < images2.length; i++)
for (int j = 0; j < images2[i].length; j++) {
ImageInfo imgs = images2[i][j];
ImageInfo imgs2 = images[i][j];
if(imgs2 == null || imgs==null || !imgs.show)continue;
Image image = imgs2.show?huiyuansu.get((int)imgs.value):yuansu.get((int)imgs.value);
double width1 = 50,height1 = 50,x = imgs.x-30,y = imgs.y+30;
if(!disable && !imgs2.show && new Rectangle2D(x, y, width1, height1).intersects(this.x,this.y,1,1)){
this.x=this.y=0;
if(!play_muisc)clip.play();
//System.out.println("第二层");
width1 += 4;height1 +=4;
//x = (width-images2.length*width1)/2+width1*i;y = 100+height1*j;
if(info1.size()<8){img_x = i;img_y = j;}
}context.drawImage(image,x,y,width1,height1);
}
//画第一层元素
for (int i = 0; i < images.length; i++)
for (int j = 0; j < images[i].length; j++) {
ImageInfo imgs = images[i][j];
if(imgs==null || !imgs.show)continue;
Image image = yuansu.get((int)imgs.value);
double width1 = 50,height1 = 50,x = imgs.x,y = imgs.y;
if(!disable && new Rectangle2D(x, y, width1, height1).intersects(this.x,this.y,1,1)){
this.x=this.y=0;
if(!play_muisc)clip.play();
//System.out.println("第一层");
width1 += 4;height1 +=4;
//x = (width-images.length*width1)/2+width1*i;y = 100+height1*j;
if(info1.size()<8){img_x = i;img_y = j;}
}context.drawImage(image,x,y,width1,height1);
}
//画按钮图片
for (int j = 0; j < info1.size(); j++) {
Image image = yuansu.get((int) info1.get(j).value);
double width1 = 50,x = 50+width1*j,y = 625;
context.drawImage(image,x,y,width1,width1);
}
//画按钮图片
for (int j = 0; j < 3; j++) {
Image image = buttons.get(j);
double width1 = 100,height1 = 65,x = (width-3*width1+j*40)/2+width1*j-20,y = 720;
if(!disable && new Rectangle2D(x, y, width1, height1).intersects(this.x,this.y,1,1)){
this.x=this.y=0;
width1 +=10;height1 +=10;
if(!play_muisc)clip.play();
//x = (width-buttons.size()*width1+j*40)/2+width1*j-20;y = 715;
switch (j) {
case 0:
System.exit(0);
break;
case 1:
rest(guanqia);
break;
case 2:
break;
}
}
context.drawImage(image,x,y,width1,height1);
}
if(status==3){
Image image = buttons.get(buttons.size()-1);
double[] wh = dengbi(image,width+40);
if(qiehuan_x == width*2){qiehuan_x = (int)(wh[0]/2+width);qiehuan = true;}
context.drawImage(image,qiehuan_x,(height-wh[1])/2,wh[0],wh[1]);
}else if(status==1){
context.setFill(Color.BLACK);
context.setGlobalAlpha(0.4);
context.fillRect(0,0,width,height);
context.setGlobalAlpha(1.0);
for (int j = 3,i=0; j < buttons.size()-1; j++,i++) {
Image image = buttons.get(j);
double[] wh = dengbi(image,220D);
double x = (width-wh[0])/2,y = 350+wh[1]*i+i*40;
if(new Rectangle2D(x, y,wh[0],wh[1]).intersects(this.x,this.y,1,1)){
this.x=this.y=0;wh[0]+=20;wh[1]+=20;
if(!play_muisc)clip.play();
if(j==3){status = 4;rest(4);}
else{status = 4;info1.clear();end_x = 50;}
}context.drawImage(image,x,y,wh[0],wh[1]);
}
Bounds bounds = getFontWH("游戏结束",font);
context.setFont(font);
context.setFill(Color.WHITE);
context.fillText("游戏结束",(width-bounds.getWidth())/2,300);
}
}
} catch (Exception e) {
e.printStackTrace();
}
});
canvas.setOnMousePressed(event->{
x=event.getX();y=event.getY();
});
}
private List<Integer> random_next_int(int count,int images){
while(true)if(count--%3==0)break;
List<Integer> list = new ArrayList<Integer>(count);
AtomicInteger integer = new AtomicInteger(0);
while(list.size()<count){
IntStream.range(0,3).forEach(m->list.add(integer.get()));
integer.incrementAndGet();
integer.set(integer.get()>images-1?random.nextInt(images):integer.get());
}
Collections.shuffle(list);
return list;
}
private static Image pixWithImage(int type,Image image){
PixelReader pixelReader = image.getPixelReader();
if(image.getWidth()>0 && image.getHeight() >0){
WritableImage wImage;
wImage = new WritableImage(
(int)image.getWidth(),
(int)image.getHeight());
PixelWriter pixelWriter = wImage.getPixelWriter();
for(int y = 0; y < image.getHeight(); y++){
for(int x = 0; x < image.getWidth(); x++){
Color color = pixelReader.getColor(x, y);
switch (type) {
case 1:
// 颜色变轻
color = color.brighter();
break;
case 2:
// 颜色变深
color = color.darker();
break;
case 3:
// 灰度化
Color colors = color.grayscale();
color = Color.color(colors.getRed(),colors.getGreen(),colors.getBlue(),0.6);
break;
case 4:
// 颜色反转
color = color.invert();
break;
case 5:
// 颜色饱和
color = color.saturate();
break;
case 6:
// 颜色不饱和
color = color.desaturate();
break;
case 7:
// 颜色灰度化后反转(字黑体,背景鲜亮,可用于强字弱景)
color = color.grayscale();
color = color.invert();
break;
default:
break;
}
pixelWriter.setColor(x, y, color);
}
}
return wImage;
}
return null;
}
@Override
public void start(Stage stage) throws Exception {
AnchorPane pane = new AnchorPane(canvas);
pane.setPadding(new Insets(0));
Scene scene = new Scene(pane,width-15,height-10);
stage.getIcons().add(icon.get(0));
stage.setTitle("羊了个羊");
stage.setScene(scene);
stage.setAlwaysOnTop(true);
stage.setResizable(false);
stage.show();
}
}
public abstract class GameStarting {
public static void main(String[] args) throws Exception {
Application.launch(FXController.class,args);
}
}