[转载] 匹諾康尼的奇幻之旅丨匹諾康尼設定考據
[转载] 匹諾康尼的奇幻之旅丨匹諾康尼設定考據前言在新版本的開拓任務中，我們來到了充滿甜蜜美夢的匹諾康尼。匹諾康尼到處充滿著繁華的氣息，其中還有美味解渴的蘇樂達，但是埋藏在匹諾康尼美好夢幻的背後卻充滿著謎團和危險。匹諾康尼多個設定中在現實也有對應的參考依據，今天就請跟隨本篇，詳細地了解充滿甜蜜美夢的匹諾康尼的相關設定吧。匹諾康尼原型考據匹諾康尼選取的時代背景原型乃是處在上世紀 20 至 30 年代、有著「咆哮的二十年代」（Roaring Twenties）之稱時期中的美國，即一戰結束後經濟社會蓬勃發展的「黃金十年」；由於恰值卡爾文 · 柯立芝任期內，故也以人名冠之稱作「柯立芝繁榮」（Coolidge Prosperity）。 這一時期以美國為代表的西方世界經濟持續繁榮，社會、藝術和文化領域充滿強勁活力，出現了前所未有的工業化與電氣化浪潮，人們的生活方式在短時間內發生了翻天覆地的徹變。由於激動人心的事件數不勝數，因此有人也稱這段時期為「歷史上最為多彩的年代」。該時期的文化藝術發展表現出強烈的創新性和前衛性，人們在物質和精神上追求全新風貌，其中最具代表性的特徵之一便是「裝飾藝術」（Art Deco）的盛行，這一風格滲透在當時建築、服飾設計等方方面面，構築出時代華麗奢靡的視覺印象，你能在匹諾康尼的夢境世界中感受到濃郁的此類美術設計。爵士樂與舞蹈在反對一戰的情緒中越來越受人們歡迎，因此這一時期亦被後世稱作「爵士時代」（Jazz Age），這一點同樣反映在了匹諾康尼的配樂風格中。社會風氣與精神風貌方面，「咆哮的二十年代」中伴隨經濟的繁榮與物質的大豐富，民眾展現出旺盛的消費需求與消費欲望，推崇純潔、節制生活的傳統道德走向土崩瓦解，「享樂主義」（Hedonism）開始在都市社會大行其道，像是紐約這樣的大都便呈現出一種濃烈的紙醉金迷的社會氛圍。這一鮮明時代特徵也反映在了匹諾康尼的背景設計中，並以自造的專有名詞「糖漿主義」（Syrupism）予以概括。然而，以 1929 年華爾街股災事件為標誌，「咆哮的二十年代」猝然宣告終結，美國開始進入「大蕭條」（The Great Depression）時代。這場發源自美國的經濟衰退災難波及全球，最終造成了自由主義經濟史上最持久、最深刻、最嚴重的週期性世界經濟危機。無數人的美夢於一夕間破碎，自高峰瞬間跌入低谷的社會一時陷入到一場充滿悲觀、混亂與困苦的噩夢中。結合這一歷史背景以及本次主線劇情中提供的線索，似乎預示了匹諾康尼的美好夢境或將面臨一場前所未見「大崩潰」的灰暗未來。鐘錶小子考據「黃金十年」時期開始萌芽的動畫藝術領域則出現了第一種標準化動畫風格，即「橡皮管動畫」（Rubber Hose Animation），著名動畫米老鼠、貓和老鼠、大力水手等經典IP都採用過橡皮管動畫。而遊戲中匹諾康尼的著名動畫 IP「鐘錶小子」就具有這種典型的復古風格。橡皮管動畫是在動畫藝術萌芽及早期有限發展條件下，藝術家們創造的一種「折衷」動畫製作模式，動畫為了減負手繪勞動強度往往不會去細究角色的動作，這使動作效果變得十分誇張同時產生出一種滑稽感，而這正創造出了此類動畫非常獨特的風格。蘇樂達考據匹諾康尼中還有人人喜愛的蘇樂達，在鐘錶小子pv動畫仲介紹了蘇樂達，畫面中巨大的蘇樂達噴湧而出，蘇樂達像下雨一樣從天上飄落。這個畫面與現實中美國波士頓蜜糖爆炸事件有些相似，也可能暗示著匹諾康尼後續的劇情會發生巨大的悲劇。美國波士頓蜜糖爆炸事件，八百萬升糖蜜因為高溫發酵產生爆炸噴湧而出，巨量的高溫粘稠的糖蜜向人們席捲而來。人們被包裹在糖蜜之中，有的人隨著糖蜜的冷卻窒息而死，而倖存者也被糖蜜黏在原地動彈不得，像是粘蠅板上的蒼蠅。這個事件造成了21人死亡150人受傷和大量馬匹死亡，隨後數年間街道上都飄蕩著甜甜的香氣。當時糖蜜是朗姆酒塔菲亞酒的原材料，美國在1919年通過法案，將在1920年施行禁酒令，而前瞻直播中提及的邪惡的典獄長將蘇樂達列為禁品，正好對應著禁酒令。匹諾康尼星球外形考據匹諾康尼的星球原型是著名科幻電影《盜夢空間》中的陀螺，在電影《盜夢空間》中，陀螺男主是用來檢測自己是否在夢境中。因為陀螺是男主夢境中的圖騰，每個人都會有一個圖騰，只要陀螺一直轉下來，那麼就會說明男主還在夢境中。而匹諾康尼的外形也是一個陀螺，暗示著我們進入匹諾康尼的時候就已經陷入了無盡的夢境之中。在遊戲劇情中，我們進入匹諾康尼之前就進入了夢境和黃泉相見，黃泉和我們的一些對話和反應，總是隱隱約約暗示著黃泉可能在夢境中經歷過多次輪回，我們可能就處於夢中夢。根據劇情各種線索推測，當我們認為在匹諾康尼的現實世界中的時候，可能就處在夢中夢的世界中。原文链接《匹諾康尼的奇幻之旅丨匹諾康尼設定考據》，LuckyPomPom_CHT，https://www.hoyolab.com/article/25726225
JavaFx实现Flappybird《flappy bird》是一款由来自越南的独立游戏开发者Dong Nguyen所开发的作品。游戏中玩家必须控制一只小鸟，跨越由各种不同长度水管所组成的障碍。现在用Java还原了这款游戏。运行截图首页游戏中结算项目文件项目文件项目源码入口main.javapackage pika.game.flappybird; /*-------------------------------------- Flappy Bird Code by Pikachu Java课程设计 任浩龙2018141461344 --------------------------------------*/ import javafx.application.Application; import javafx.stage.Stage; import javafx.scene.text.Text; public class Main extends Application { //----------------------------------------------全局游戏设置参数---------------------------------------------- public static final int game_wind_high = 960; //全局窗口高度 public static final int game_wind_wedh = 864; //全局窗口宽度 public static final int game_fram_fpst = 17; //全局同步间隔 public static final int game_dbug_imgs = 0; //图像调试标识 public static final int game_dbug_taps = 1; //水管调试标识 public static final double bird_data_datg =0.45; //记录小鸟重力 public static double bird_data_high = 330; //记录小鸟位置 public static double bird_data_spee = 0; //记录小鸟速度，每一帧执行后自增的速度 public static final double bird_data_addq = 10; //小鸟上升速度，每次按下鼠标设置的速度 public static double taps_spee_init = 6; //记录水管速度 public static final double taps_spee_adda = 0; //水管递增速度，每隔多少帧增加多少速度 public static double taps_spee_addb = 140; //水管递增间隔，每隔多少帧增加一根水管 public static final double taps_spee_addc = 2; //水管递增递减，每通过一根水管减多少帧 public static double taps_spee_addd = 0; //水管递增计数，统计当前执行的是多少帧 public static final double taps_spee_adde = 30; //水管递增下界，记录最少间隔多少帧自增 public static double game_scor_data = 0; //存储游戏分数 public static Imgs main_ctrl = new Imgs(); //全局渲染对象 public static Imgs menu_bgmp = new Imgs(); //菜单背景图片 public static Imgs menu_titl = new Imgs(); //菜单标题图片 public static Imgs menu_star = new Imgs(); //菜单开始图片 public static Imgs menu_bars = new Imgs(); //菜单底纹图片 public static Imgs menu_bart = new Imgs(); //菜单底纹图片 public static Imgs game_bird = new Imgs(); //游戏小鸟图像 public static Imgs ends_titl = new Imgs(); //游戏结束标题 public static Imgs ends_pans = new Imgs(); //游戏结束标题 public static Imgs ends_dold = new Imgs(); //游戏结束标题 public static Push menu_butt = new Push(); //存储按钮数据 public static Loop menu_loop = new Loop(); //存储菜单循环 public static Loop bird_loop = new Loop(); //小鸟下坠循环 public static Loop taps_loop = new Loop(); //水管移动循环 public static Taps taps_maps = new Taps(); //水管图像数据 public static Text text_scor = new Text(); //存储文字信息 public void start(Stage views) { Func.main_init(views); Func.main_menu_init(); Func.main_menu_show(); Func.main_menu_loop(); Func.menu_loop.play(); Func.main_push_init(); Func.main_mous_loop(); Func.main_game_loop(); } }功能实现游戏渲染Func.javapackage pika.game.flappybird; /*-------------------------------------- 渲染事件类 CODE BY PIKACHUIM 作用：执行渲染操作 --------------------------------------*/ import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.input.MouseEvent; import javafx.stage.Stage; import javafx.scene.text.Font; import javafx.scene.paint.Paint; public class Func extends Main{ public static void main_init(Stage inpu) { main_ctrl.init(game_wind_high, game_wind_wedh);main_ctrl.show(inpu); } public static void main_menu_init() { //----------------------------------------------主菜单图片初始化---------------------------------------------- menu_bgmp.setp("Imgs", "PICTS_BGPBT");menu_bgmp.setr(000, 000, 864, 960); menu_titl.setp("Imgs", "PICTS_TITLE");menu_titl.setr(170, 100, 534, 144); menu_star.setp("Imgs", "PICTS_START");menu_star.setr(315, 330, 242, 146); menu_bars.setp("Imgs", "PICTS_LANGS");menu_bars.setr(000, 852, 864, 224); menu_bart.setp("Imgs", "PICTS_LANGS");menu_bart.setr(864, 852, 864, 224); ends_titl.setp("Imgs", "PICTS_OVERD");ends_titl.setr(130, 140, 612, 108); ends_pans.setp("Imgs", "PICTS_PANEL");ends_pans.setr(150, 500, 595, 315); ends_dold.setp("icon", "PICTS_MEDA3");ends_dold.setr(219, 625, 110, 110); menu_butt = new Push("", menu_star); menu_butt.setr(295, 300);menu_butt.tran(); } public static void main_game_init(){ //----------------------------------------------游戏中图片初始化---------------------------------------------- game_bird.setp("icon", "PICTS_BIRD1");game_bird.setr(340,330, 96, 96); main_bird_loop();bird_loop.play();Func.taps_loop.play(); } public static void main_game_loop(){ //----------------------------------------------游戏中水管主循环---------------------------------------------- EventHandler<ActionEvent> main_taps_even = r -> { Taps.move(); if(taps_spee_addd==0){ int temp_addu=(int)System.currentTimeMillis()%150; int temp_flag=(int)(Math.random()*101)%2; if(Taps.taps_lens>0){ int temp_posy=(int)(-Taps.taps_dat1.get(Taps.taps_lens-1).imgs_posy); if(temp_flag==0) Taps.addt(temp_posy+temp_addu); else Taps.addt(temp_posy-temp_addu); System.out.println("[增加水管]"+temp_flag+"[增加位置]"+temp_posy); } else Taps.addt(700); taps_spee_init+=taps_spee_adda; taps_spee_addd=taps_spee_addb; } else{ taps_spee_addd--; } }; taps_loop.setb(game_fram_fpst, main_taps_even); } public static void main_menu_show(){ //----------------------------------------------载入菜单图像数据---------------------------------------------- main_ctrl.clea();/*清空*/menu_bgmp.radd();menu_titl.radd();menu_bars.radd();menu_bart.radd();menu_butt.radd(); } public static void main_game_show(){ //----------------------------------------------载入游戏图像数据---------------------------------------------- main_ctrl.clea();/*清空*/menu_bgmp.radd();menu_bars.radd();menu_bart.radd();game_bird.radd(); text_scor.setFont(Font.font ("Verdana", 42)); text_scor.setText("SCORE: 0"); text_scor.setTranslateX(20); text_scor.setTranslateY(70); text_scor.setFill(Paint.valueOf("#ffffff")); main_ctrl.imgs_pane.getChildren().add(text_scor); } public static void main_push_init(){ //----------------------------------------------载入菜单按钮事件---------------------------------------------- EventHandler<ActionEvent> menu_burr_acte=new EventHandler<ActionEvent>(){ @Override public void handle(ActionEvent t){ main_game_init();main_game_show(); }}; menu_butt.seta(menu_burr_acte); } public static void main_menu_loop(){ //----------------------------------------------载入菜单底栏事件---------------------------------------------- EventHandler<ActionEvent> main_menu_even = r -> { menu_bars.setr(menu_bars.imgs_posx -8, menu_bars.imgs_posy); menu_bart.setr(menu_bart.imgs_posx -8, menu_bart.imgs_posy); if(menu_bars.imgs_posx<=game_wind_wedh*(-1)) menu_bars.setr( 0,menu_bars.imgs_posy); if(menu_bart.imgs_posx<=0) menu_bart.setr(864,menu_bart.imgs_posy);}; menu_loop.setb(game_fram_fpst,main_menu_even); } public static void main_bird_loop(){ //----------------------------------------------载入小鸟下坠线程---------------------------------------------- EventHandler<ActionEvent> main_bird_even = r -> { bird_data_spee+=bird_data_datg;bird_data_high+=bird_data_spee; if(bird_data_high>=778)bird_data_high=778;game_bird.setr(game_bird.imgs_posx,bird_data_high);}; bird_loop.setb(game_fram_fpst,main_bird_even); } public static void main_mous_loop(){ //----------------------------------------------载入小鸟上升线程---------------------------------------------- main_ctrl.imgs_rend.setOnMousePressed(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent m) { bird_data_spee=-bird_data_addq; }}); } public static void main_game_rset(){ //----------------------------------------------重置游戏状态函数---------------------------------------------- bird_data_high = 330; //记录小鸟位置 bird_data_spee = 0; //记录小鸟速度 taps_spee_init = 6; //记录水管速度 taps_spee_addb = 140; //水管递增间隔 taps_spee_addd = 0; //水管递增计数 game_scor_data = 0; //存储游戏分数 for ( int i=Taps.taps_dat1.size()-1; i>=0;i--) { Taps.taps_dat1.remove(i); Taps.taps_dat2.remove(i); } } public static void main_endl_show(){ //----------------------------------------------显示结尾标题函数---------------------------------------------- bird_loop.stop(); taps_loop.stop(); main_ctrl.clea(); menu_bgmp.radd(); ends_titl.radd(); ends_pans.radd(); ends_dold.radd(); text_scor.setTranslateX(620); text_scor.setTranslateY(620); main_ctrl.imgs_pane.getChildren().add(text_scor); Taps.clen(); text_scor.setText(Integer.toString((int)game_scor_data)); main_game_rset(); menu_butt.radd(); } }图片载入Imgs.javapackage pika.game.flappybird; /*-------------------------------------- 图片渲染类 CODE BY PIKACHUIM 作用：载入图片并执行渲染，并绑定面板布局 用法：Imgs->setp->setr->load->uppo->radd 全局：init传入场景->show一次性绑定节点值 --------------------------------------*/ import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.Pane; public class Imgs { public static Pane imgs_pane; //存储全局布局 public static Scene imgs_rend; //存储全局场景 public String imgs_path; //存储图片位置 public Image imgs_imgs; //存储图形数据 public ImageView imgs_view; //存储图片参数 public double imgs_posx; //存储垂直坐标 public double imgs_posy; //存储水平坐标 public double imgs_posw; //存储水平宽度 public double imgs_posh; //存储垂直宽度 //--------------------------构造函数-------------------------- public Imgs() { this.news(); } //默认构造函数 public Imgs(String dirs, String name){ //只设置文件名 this.setp(dirs,name);this.news();} public Imgs(String dirs, String name, //同时设置状态 double datx, double daty, double datw, double dath){ this.setp(dirs,name); this.setr(datx,daty, datw,dath);} public void news() { //默认参数初始 this.imgs_posx = 0; this.imgs_posw = 100; this.imgs_posy = 0; this.imgs_posh = 100; } //--------------------------设置函数-------------------------- public void setp(String dirs,String name) {//设置文件路径 imgs_path = "file:" + System.getProperty("user.dir") + "\\" + dirs + "\\" + name + ".PNG"; this.load(); } public void setr(double datx, double daty, double datw, double dath) {//设置大小位置 this.imgs_posw = datw; this.imgs_posh = dath; this.setr(datx, daty); } public void setr(double datx, double daty) {//改变图片位置 this.imgs_posx = datx; this.imgs_posy = daty; this.uppo(); } //--------------------------载入函数-------------------------- public void load() { this.imgs_imgs = new Image(imgs_path); //载入图片文件 this.imgs_view = new ImageView(); this.imgs_view.setImage(imgs_imgs); if(Main.game_dbug_imgs==1) System.out.println(imgs_path); this.uppo(); } public void radd() { //向面板加节点 this.imgs_pane.getChildren().add(imgs_view); } public void uppo() { //更新图片位置 this.imgs_view.setFitHeight(imgs_posh); this.imgs_view.setFitWidth(imgs_posw); this.imgs_view.setX(imgs_posx); this.imgs_view.setY(imgs_posy); } //--------------------------全局函数-------------------------- public void init(int high, int widh) { //初始窗口界面 this.imgs_pane = new Pane(); this.imgs_rend = new Scene( imgs_pane,widh,high); } public void show(Stage runt) { //更新窗口画面 runt.setScene(imgs_rend); runt.show(); } public void clea() { //清空渲染内容 this.imgs_pane.getChildren().clear(); } //------------------------------------------------------------ } 事件载入Loop.javapackage pika.game.flappybird; /*-------------------------------------- 事件循环类 CODE BY PIKACHUIM 作用：读写事件操作 --------------------------------------*/ import javafx.animation.KeyFrame; import javafx.animation.Timeline; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.util.Duration; public class Loop { public EventHandler<ActionEvent> loop_even; public Timeline loop_line; public double loop_time; public void setb(double inpu_time,EventHandler<ActionEvent>inpu_even){ //绑定事件 loop_time=inpu_time; loop_even=inpu_even; } public void play(){ loop_line=new Timeline(new KeyFrame(Duration.millis(loop_time),loop_even)); //执行动画 loop_line.setCycleCount(Timeline.INDEFINITE); loop_line.play(); } public void stop(){ //停止执行 loop_line.stop(); } }按钮事件Push.javapackage pika.game.flappybird; /*-------------------------------------- 按钮事件类 CODE BY PIKACHUIM 作用：显示按钮并绑定触发事件 用法：Push->setr->radd->seta --------------------------------------*/ import javafx.scene.control.Button; import javafx.event.ActionEvent; import javafx.event.EventHandler; public class Push extends Imgs { public Button push_push; public Push(){} public Push(String text, Imgs imga){ push_push=new Button(text,imga.imgs_view); } public void setr(double datx,double daty){ push_push.setLayoutX(datx); push_push.setLayoutY(daty); } public void radd(){ this.imgs_pane.getChildren().add(push_push); } public void seta(EventHandler<ActionEvent> inpu){ push_push.setOnAction(inpu); } public void tran(){ push_push.setStyle("-fx-background-color: #4ec0ca"); } } 水管事件Taps.javapackage pika.game.flappybird; import java.util.ArrayList; import java.util.List; /*-------------------------------------- 水管移动类 CODE BY PIKACHUIM 作用：操作水管移动并判断 --------------------------------------*/ public class Taps extends Main{ public static List<Imgs> taps_dat1; public static List<Imgs> taps_dat2; public static int taps_lens; public Taps(){ taps_lens=0; taps_dat1= new ArrayList<Imgs>(); taps_dat2= new ArrayList<Imgs>(); } public static void clen(){ taps_lens=0; taps_dat1= new ArrayList<Imgs>(); taps_dat2= new ArrayList<Imgs>(); } public static void addt(int high){ if(high<300) high=300; if(high>600) high=600; taps_lens++; Imgs tmp1=new Imgs("icon","PICTS_PIPUP", 820, -high, 52,768); Imgs tmp2=new Imgs("icon","PICTS_PIPDO", 820,-high+768+300,52,768); taps_dat1.add(tmp1);taps_dat1.get(taps_dat1.size()-1).radd(); taps_dat2.add(tmp2);taps_dat2.get(taps_dat2.size()-1).radd(); } public static void delt(int inde){ if(taps_dat1.size()>=1){ main_ctrl.imgs_pane.getChildren().remove(taps_dat1.get(inde).imgs_view); main_ctrl.imgs_pane.getChildren().remove(taps_dat2.get(inde).imgs_view); taps_dat1.remove(taps_dat1.get(inde)); taps_dat2.remove(taps_dat2.get(inde)); taps_lens--; } } public static void move(){ if(taps_lens>0) for(int lotp=0;lotp<taps_lens;lotp++){ taps_dat1.get(lotp).setr(taps_dat1.get(lotp).imgs_posx-taps_spee_init,taps_dat1.get(lotp).imgs_posy); taps_dat2.get(lotp).setr(taps_dat2.get(lotp).imgs_posx-taps_spee_init,taps_dat2.get(lotp).imgs_posy); if(taps_dat1.get(lotp).imgs_posx<=-64) { game_scor_data++; String temp="SCORE: "+Integer.toString((int)game_scor_data); text_scor.setText(temp); if(Main.game_dbug_taps==1) System.out.println("[当前得分]"+game_scor_data +"[帧率间隔]"+taps_spee_addb +"[水管速度]"+taps_spee_init +"[水管数量]"+taps_lens); taps_spee_addb-=taps_spee_addc; if(taps_spee_addb<=taps_spee_adde)taps_spee_addb=taps_spee_adde; } if(taps_dat1.get(lotp).imgs_posx<=-64){ delt(lotp); } if(taps_dat1.get(lotp).imgs_posx>=244&&taps_dat1.get(lotp).imgs_posx<=436){ if(bird_data_high<= taps_dat1.get(lotp).imgs_posy+750 || bird_data_high>= taps_dat2.get(lotp).imgs_posy-80){ System.out.println("[撞到柱子]"+lotp); Func.main_endl_show(); } } } } }
《flappy bird》是一款由来自越南的独立游戏开发者Dong Nguyen所开发的作品。游戏中玩家必须控制一只小鸟，跨越由各种不同长度水管所组成的障碍。现在用Python还原了这款游戏。项目地址：https://github.com/PIKACHUIM/PIKA-PY3-FlappyBird项目文件：【点击下载】游戏源码import pygame from pygame.locals import * from sys import exit import random # -----------------------------设置全局变量----------------------------- GAME_WINDP_HEIGH = 864 # 窗口高度 # GAME_WINDP_WEDTH = 1024 # 窗口宽度 GAME_WINDP_WEDTH = 960 # 窗口宽度 GAME_WINDP_BASEY = 432 # 中心高度 GAME_PIPES_WIDTH = 52 # 管子宽度 GAME_PIPES_HEIGH = 512 # 管子高度 GAME_PIPES_GAPSZ = 10 # 水管间距 GAME_BIRDS_WIDTH = 48 # 小鸟宽度 GAME_BIRDS_HEIGH = 48 # 小鸟高度 global BIRD_X global BIRD_Y global BIRD_V BIRD_X = 420 BIRD_Y = 432 BIRD_V = 0 WIND_WINDP = pygame.display.set_mode((GAME_WINDP_HEIGH, GAME_WINDP_WEDTH)) # -----------------------------设置全局变量----------------------------- class IMGS: POSX = 0 POSY = 0 POSW = 0 POSH = 0 NAME = "" def __init__(self, NAME): self.NAME = NAME self.DATA = pygame.image.load("./ASSE/PICTS_" + NAME + ".PNG").convert_alpha() def PICS(self, NAME): self.NAME = NAME self.DATA = pygame.image.load("./ASSE/PICTS_" + NAME + ".PNG").convert_alpha() def SETP(self, X, Y, W, H): self.POSX = X self.POSY = Y self.POSW = W self.POSH = H def SHOW(self): WIND_WINDP.blit(self.DATA, (self.POSX, self.POSY, self.POSW, self.POSH)) def GAME_PIPE(): # 两个水管之间的距离有如下变量 PIPE_GAPS = [100, 200, 300, 400] PIPE_PIJG = [60, 90, 120, 150, 180] PIPE_RAND = random.randint(0, len(PIPE_GAPS) - 1) PIPE_GAPY = PIPE_GAPS[PIPE_RAND] PIPE_RAND = random.randint(0, len(PIPE_PIJG) - 1) PIPE_PIJR = PIPE_PIJG[PIPE_RAND] PIPE_GAPX = GAME_WINDP_WEDTH + 10 return [ {'x': PIPE_GAPX, 'y': PIPE_GAPY - GAME_PIPES_WIDTH - 600 - PIPE_PIJR}, # 上面水管的左上角位置 {'x': PIPE_GAPX, 'y': PIPE_GAPY + GAME_PIPES_HEIGH - 300 + PIPE_PIJR}, # 下面水管的左上角位置 ] def GAME_INIT(): pygame.init() pygame.display.set_caption("Flappy Bird") pygame.mixer.music.load("./ASSE/MUSIC_BGM.WAV") global REND_BGPBT global REND_BGPHY global REND_START global REND_TITLE global REND_BIRD1 global REND_BIRD2 global REND_BIRD3 global REND_BIRDS global REND_PIPUP global REND_PIPDO global REND_STTIP global REND_LANGS global REND_OVERD global REND_SCORE global REND_PANEL REND_BGPBT = IMGS("BGPBT") REND_BGPHY = IMGS("BGPHY") REND_START = IMGS("START") REND_TITLE = IMGS("TITLE") REND_BIRDS = IMGS("BIRD1") REND_BIRD1 = IMGS("BIRD1") REND_BIRD2 = IMGS("BIRD2") REND_BIRD3 = IMGS("BIRD3") REND_PIPUP = IMGS("PIPUP") REND_PIPDO = IMGS("PIPDO") REND_STTIP = IMGS("STTIP") REND_LANGS = IMGS("LANGS") REND_OVERD = IMGS("OVERD") REND_PANEL = IMGS("PANEL") REND_SCORE = [] REND_BGPBT.SETP(000, 000, 576, 1024) REND_BGPHY.SETP(000, 000, 576, 1024) REND_START.SETP(320, 330, 170, 48) REND_TITLE.SETP(170, 140, 170, 48) REND_STTIP.SETP(170, 140, 170, 48) REND_OVERD.SETP(130, 200, 170, 48) REND_PANEL.SETP(135, 350, 170, 48) REND_LANGS.SETP(0, 0, 100, 100) for i in range(10): REND_SCORE.append(IMGS("NUML" + str(i))) REND_SCORE[i].SETP(0, 0, 24, 44) pygame.mixer.init() # SOUND_BGM = pygame.mixer.music.load("") pygame.mixer.music.set_volume(0.5) def GAME_OVER(STATUE, BIRD_SCOE): with open('./ASSE/SAVE.DAT', 'r+') as f: LAST_SCOE = int(f.read()) f.close() if LAST_SCOE < BIRD_SCOE: with open('./ASSE/SAVE.DAT', 'w+') as f: f.write(str(BIRD_SCOE)) if BIRD_SCOE <= 9: MSTR = 'MEDA' + str(0) elif BIRD_SCOE <= 49: MSTR = 'MEDA' + str(1) elif BIRD_SCOE <= 99: MSTR = 'MEDA' + str(2) else: MSTR = 'MEDA' + str(3) REND_MEDAL = IMGS(MSTR) REND_MEDAL.SETP(210,475,96,96) SOUND_DIE = pygame.mixer.Sound("./ASSE/MUSIC_DIE.WAV") pygame.time.delay(1000) SOUND_DIE.play() pygame.time.delay(300) if STATUE == 1: REND_BIRDS.SETP(BIRD_X, BIRD_Y, 48, 48) REND_BIRDS.SHOW() REND_OVERD.SHOW() REND_PANEL.SHOW() REND_START.SETP(320, 700, 170, 48) REND_START.SHOW() SCOE_B = BIRD_SCOE // 100 SCOE_S = BIRD_SCOE %100 // 10 SCOE_G = BIRD_SCOE % 10 REND_SCORE[SCOE_G].SETP(630, 450, 24, 44) REND_SCORE[SCOE_G].SHOW() REND_SCORE[SCOE_S].SETP(600, 450, 24, 44) REND_SCORE[SCOE_S].SHOW() REND_SCORE[SCOE_B].SETP(570, 450, 24, 44) REND_SCORE[SCOE_B].SHOW() SCOE_B = LAST_SCOE // 100 SCOE_S = LAST_SCOE %100 // 10 SCOE_G = LAST_SCOE % 10 REND_SCORE[SCOE_G].SETP(630, 560, 24, 44) REND_SCORE[SCOE_G].SHOW() REND_SCORE[SCOE_S].SETP(600, 560, 24, 44) REND_SCORE[SCOE_S].SHOW() REND_SCORE[SCOE_B].SETP(570, 560, 24, 44) REND_SCORE[SCOE_B].SHOW() REND_MEDAL.SHOW() pygame.display.update() while 1: for GAME_EVENT in pygame.event.get(): if GAME_EVENT.type == QUIT: exit(0) if GAME_EVENT.type == MOUSEBUTTONUP: EVEN_MOUSE_X, EVEN_MOUSE_Y = GAME_EVENT.pos if EVEN_MOUSE_X >= 320 and EVEN_MOUSE_X <= 540 and EVEN_MOUSE_Y >= 700 and EVEN_MOUSE_Y <= 450 + 370: return def GAME_MENU(): OFPS_NUMS = 60 OFPS_LOCK = pygame.time.Clock() while True: REND_BGPBT.SHOW() REND_START.SETP(320, 330, 170, 48) REND_START.SHOW() REND_TITLE.SHOW() REND_LANGS.SETP(REND_LANGS.POSX - 2, 850, 52, 320) REND_LANGS.SHOW() REND_LANGS.SETP(REND_LANGS.POSX + 940, 850, 52, 320) REND_LANGS.SHOW() REND_LANGS.SETP(REND_LANGS.POSX - 943, 850, 52, 320) pygame.display.update() if pygame.mixer.music.get_busy() == False: pygame.mixer.music.play() if REND_LANGS.POSX <= -941: REND_LANGS.SETP(0, 850, 52, 320) for GAME_EVENT in pygame.event.get(): if GAME_EVENT.type == QUIT: exit() if GAME_EVENT.type == MOUSEBUTTONUP: EVEN_MOUSE_X, EVEN_MOUSE_Y = GAME_EVENT.pos if EVEN_MOUSE_X >= 320 and EVEN_MOUSE_X <= 540 and EVEN_MOUSE_Y >= 330 and EVEN_MOUSE_Y <= 450: GAME_GAME() OFPS_LOCK.tick(OFPS_NUMS) def GAME_GAME(): BIRD_V = 0 OFPS_NUMS = 60 OFPS_LOCK = pygame.time.Clock() BIRD_Y = 300 # 小鸟状态 PIPE_SPEX = -4 # 管道速度 PIPE_SPEO = -4 # 初始速度 PIPE_NEWP = GAME_PIPE() PIPE_UPPS = [{'x': GAME_WINDP_WEDTH, 'y': PIPE_NEWP[0]['y']}] PIPE_DOPS = [{'x': GAME_WINDP_WEDTH, 'y': PIPE_NEWP[1]['y']}] BIRD_SCOE = 0 GAME_TIME = pygame.time.get_ticks() GAME_LAST = GAME_TIME BIRD_SCOE += 0 # 跳关数 SOUND_POT = pygame.mixer.Sound("./ASSE/MUSIC_POT.WAV") SOUND_PAS = pygame.mixer.Sound("./ASSE/MUSIC_PAS.WAV") SOUND_HIT = pygame.mixer.Sound("./ASSE/MUSIC_HIT.WAV") while True: if pygame.mixer.music.get_busy() == False: pygame.mixer.music.play() for GAME_EVENT in pygame.event.get(): if GAME_EVENT.type == QUIT: exit(0) if GAME_EVENT.type == MOUSEBUTTONUP or GAME_EVENT.type == KEYDOWN: BIRD_V = -15 - BIRD_SCOE / 48 SOUND_POT.play() if BIRD_V <= -16: BIRD_V = -16 if BIRD_V < 0: BIRD_Y += BIRD_V BIRD_V += 1 else: BIRD_A = 0.5 + BIRD_SCOE / 96 if BIRD_A >= 1: BIRD_A = 1 BIRD_V += BIRD_A BIRD_Y += BIRD_V BIRD_Y = BIRD_Y + 3 if BIRD_Y > GAME_WINDP_HEIGH - 80: SOUND_HIT.play() GAME_OVER(0, BIRD_SCOE) return if BIRD_Y < 0: BIRD_Y = 0 BIRD_V = 5 if BIRD_SCOE // 10 % 2 == 0: REND_BGPBT.SHOW() else: REND_BGPHY.SHOW() for PIPE_SET_UP, PIPE_SET_DO in zip(PIPE_UPPS, PIPE_DOPS): REND_PIPUP.SETP(PIPE_SET_UP['x'], PIPE_SET_UP['y'], 52, 320) REND_PIPDO.SETP(PIPE_SET_DO['x'], PIPE_SET_DO['y'], 52, 320) REND_PIPUP.SHOW() REND_PIPDO.SHOW() REND_LANGS.SETP(REND_LANGS.POSX - 3, 850, 52, 320) REND_LANGS.SHOW() REND_LANGS.SETP(REND_LANGS.POSX + 941, 850, 52, 320) REND_LANGS.SHOW() REND_LANGS.SETP(REND_LANGS.POSX - 944, 850, 52, 320) if REND_LANGS.POSX <= -941: REND_LANGS.SETP(0, 850, 52, 320) if BIRD_X >= PIPE_SET_UP['x'] - 50 and BIRD_X <= PIPE_SET_UP['x'] + 52: if BIRD_Y >= PIPE_SET_DO['y'] - 60 or BIRD_Y <= PIPE_SET_UP['y'] + 740: SOUND_HIT.play() GAME_OVER(1, BIRD_SCOE) return if BIRD_SCOE // 10 % 3 == 0: REND_BIRDS = REND_BIRD1 elif BIRD_SCOE // 10 % 3 == 1: REND_BIRDS = REND_BIRD2 else: REND_BIRDS = REND_BIRD3 REND_BIRDS.SETP(BIRD_X, BIRD_Y, 48, 48) REND_BIRDS.SHOW() SCOE_B = (BIRD_SCOE // 100) SCOE_S = BIRD_SCOE % 100 // 10 SCOE_G = BIRD_SCOE % 10 REND_SCORE[SCOE_G].SETP(90, 30, 24, 44) REND_SCORE[SCOE_G].SHOW() REND_SCORE[SCOE_S].SETP(60, 30, 24, 44) REND_SCORE[SCOE_S].SHOW() REND_SCORE[SCOE_B].SETP(30, 30, 24, 44) REND_SCORE[SCOE_B].SHOW() for PIPE_SET_UP, PIPE_SET_DO in zip(PIPE_UPPS, PIPE_DOPS): PIPE_SET_UP['x'] += PIPE_SPEX PIPE_SET_DO['x'] += PIPE_SPEX # 当水管移动到某一位置的时候，生成新的水管 GAME_TIME = pygame.time.get_ticks() GAME_TTDS = 3000 - BIRD_SCOE * 50 if GAME_TTDS <= 600: GAME_TTDS = 600 if int(GAME_TIME - GAME_LAST) > GAME_TTDS: PIPE_NEWS = GAME_PIPE() PIPE_UPPS.append(PIPE_NEWS[0]) PIPE_DOPS.append(PIPE_NEWS[1]) GAME_LAST = GAME_TIME BIRD_SCOE += 1 SOUND_PAS.play() PIPE_SPEX = PIPE_SPEO - BIRD_SCOE / 20 if PIPE_SPEX <= -10: PIPE_SPEX = -10 # 如果水管从右往左移动到边缘，则摧毁水管 if PIPE_UPPS[0]['x'] < -10: # 队列头出队 PIPE_UPPS.pop(0) PIPE_DOPS.pop(0) # 刷新画面 pygame.display.update() OFPS_LOCK.tick(OFPS_NUMS) while 1: GAME_INIT() GAME_MENU()
C++与SDL实现奔跑吧叽咔CPP+SDL引擎实现奔跑吧叽卡（No jumping）是游戏工作室Ticktock正式发布的第四款游戏 叽卡是一只不会飞也不会跳的小鸟，只会用柔软的肚皮向前走 环游世界是它最大的梦想，冰雪王国，月光之城，魔法森林…… 现在我用C++与SDL渲染移植了这个游戏 项目地址：https://github.com/PIKACHUIM/PIKA-CPP-NoJumping源代码文件二进制文件游戏截图菜单界面：游戏界面：过关界面：工程架构入口main.cpp:#undef main #include "./EXTL/WIND.CPP" #include "./LIBS/REND.CPP" #include "MENU.CPP" int main(int argc,char *argv[]) { WIND_INIT(argc,argv); REND_INIT(); MENU_INIT(); MENU_SHOW(); WIND_EXIT(); return 0; }主菜单menu.cpp#pragma once #ifndef MENU_CPP #define MENU_CPP #include"LIBS/IMGS.CPP" #include"LIBS/READ.CPP" #include"LIBS/TYPE.CPP" #include"LIBS/REND.CPP" #include"LIBS/TYPE.CPP" #include"EXTL/WIND.CPP" #include"EXTL/HEAD.CPP" #include"YXXY.CPP" static int BIRD_POTS = rand()%10+3; //将小鸟位置绑定 static SDE MENU_EVEN; //初始化事件对象 static IMGS MENU_FKYPS[15]; //创建主菜单方块 static IMGS MENU_MENUS[ 8]; //创建主菜单控件 static READ MENU_LOADS("MAPS","MAP","MENU",1,5); //读取主菜单配置 static IMGS MENU_BIRDS; //创建主菜单小鸟 static TYPE FKTP[6][4]; //初始化渲染数据 static double TIME_LAST = SDL_GetTicks(); //初始化上次时间 static double TIME_LOOP = SDL_GetTicks(); //初始化当前时间 int MENU_INIT() { for(int LOOP_A=1;LOOP_A<=7 ;LOOP_A++) //读取菜单控件 MENU_MENUS[LOOP_A].SETP("MENU", //种类 MENU_LOADS.DATA[LOOP_A][1], //编号 MENU_LOADS.DATA[LOOP_A][2], //水平 MENU_LOADS.DATA[LOOP_A][3], //垂直 MENU_LOADS.DATA[LOOP_A][4], //宽度 MENU_LOADS.DATA[LOOP_A][5]); //高度 for(int LOOP_T=0;LOOP_T<=14;LOOP_T++){ //设置方块状态 MENU_FKYPS[LOOP_T].IMGS_IMGS_UPDO=1; //向上 MENU_FKYPS[LOOP_T].SETP("FKYP", //种类 rand()%3+1+(rand()%5+1)*10, //颜色 000+100*LOOP_T, //水平 400+ 20*LOOP_T, //垂直 81,511);} //大小 for(int LOOP_A= 0,LOOP_T=1; //设置类型数据 LOOP_A<=5;LOOP_A++,LOOP_T++) for(int LOOP_B=1;LOOP_B<=3;LOOP_B++) FKTP[LOOP_A][LOOP_B].SETP( LOOP_A*10+LOOP_B,LOOP_T); BIRD_POTS = rand()%10+3; //小鸟位置绑定 MENU_BIRDS.SETP("BIRD",01,440,000,71,57); //拷贝小鸟图形 YXXY_INIT(); //初始化分菜单 return 0; } int MENU_UPDA(int count) { if ((SDL_GetTicks() - TIME_LOOP) / 1 > 1) { for(int LOOP_TMPS=0;LOOP_TMPS<=14;LOOP_TMPS++) { if(MENU_FKYPS[LOOP_TMPS].IMGS_IMGS_POST.y==700) MENU_FKYPS[LOOP_TMPS].IMGS_IMGS_UPDO=-1; if(MENU_FKYPS[LOOP_TMPS].IMGS_IMGS_POST.y==450) MENU_FKYPS[LOOP_TMPS].IMGS_IMGS_UPDO= 1; MENU_FKYPS[LOOP_TMPS].SETP(MENU_FKYPS[LOOP_TMPS].IMGS_IMGS_POST.x, MENU_FKYPS[LOOP_TMPS].IMGS_IMGS_POST.y+MENU_FKYPS[LOOP_TMPS].IMGS_IMGS_UPDO,81,511); } TIME_LOOP = SDL_GetTicks(); } if ((SDL_GetTicks() - TIME_LAST) / 1000 > 1) { DBUG_TFPS(count," RUNT_RENDER"," FPS"); count = 0; TIME_LAST = SDL_GetTicks(); } return 0; } int MENU_BIRD(int MENU_BIRD_POTS) { MENU_BIRDS.SETP( MENU_FKYPS[MENU_BIRD_POTS].IMGS_IMGS_POST.x+12, MENU_FKYPS[MENU_BIRD_POTS].IMGS_IMGS_POST.y+ MENU_FKYPS[MENU_BIRD_POTS].IMGS_IMGS_UPDO-57, 71,57); return 0; } int MENU_PDAN(int MENU_PDAN_X,int MENU_PDAN_Y,int x1,int y1,int x2,int y2) { if(MENU_PDAN_X<x1||MENU_PDAN_X>x1+x2) return 0; if(MENU_PDAN_Y<y1||MENU_PDAN_Y>y1+y2) return 0; return 1; } int MENU_DEAL() { while (SDL_PollEvent(&MENU_EVEN)) { if(MENU_EVEN.type==SDL_QUIT) WIND_EXIT(); //关闭窗口 if(MENU_EVEN.type==SDL_MOUSEBUTTONUP) { int MENU_EVENT_X=MENU_EVEN.button.x; int MENU_EVENT_Y=MENU_EVEN.button.y; if(MENU_PDAN(MENU_EVENT_X, MENU_EVENT_Y, 452,300, 270,66)==1) { YXXY_INIT(); YXXY_INFT(); //闯关模式 break; } if(MENU_PDAN(MENU_EVENT_X, MENU_EVENT_Y, 760,300, 270,66)==1) continue; //生存模式 } } return 0; } int MENU_SHOW() { for(int count=1;;count++) { REND_CLEN(); //清空渲染 for(int LOOP_A=1;LOOP_A<=7 ;LOOP_A++) MENU_MENUS[LOOP_A].SHOW(); //渲染菜单 for(int LOOP_A=0;LOOP_A<=14;LOOP_A++) MENU_FKYPS[LOOP_A].SHOW(); //渲染方块 MENU_BIRD(BIRD_POTS); //绑定小鸟 MENU_BIRDS .SHOW(); //渲染小鸟 REND_SHOW(); //执行渲染 MENU_DEAL(); //处理事件 MENU_UPDA(count); //输出帧率 } } #endif 选择菜单YXXY.CPP#include"LIBS/IMGS.CPP" #include"LIBS/REND.CPP" #include"LIBS/FONT.CPP" #include"EXTL/HEAD.CPP" #include"EXTL/WIND.CPP" #include"CGMS.CPP" #include "SDL_ttf.h" int YXXY_XZFW[16][5]; int YXXY_XZXZ[16][5]; SDE YXXY_EVEN; IMGS YXXY_BGMP[22]; IMGS YXXY_BGFA[16]; IMGS YXXY_STAR[11][4]; SAVE YXXY_DATA; READ YXXY_DQFW; READ YXXY_DQXZ; READ YXXY_CHIL; int BOTT_DEAL(int ix,int iy,int FTTL[16][5],int LTNS) //获取鼠标按钮编号 { for(int LOOP=1;LOOP<=LTNS;LOOP++) { int PDSJ_FLAG=0; if(ix<FTTL[LOOP][1] ||ix>FTTL[LOOP][2])PDSJ_FLAG=1; if(iy<FTTL[LOOP][3] ||iy>FTTL[LOOP][4])PDSJ_FLAG=1; if(PDSJ_FLAG==0) return LOOP; } return 0; } int YXXY_INIT() { SDL_PollEvent(&YXXY_EVEN);//初始化事件 //---------------配置复制:一级菜单------------------------- for(int i=1;i<=YXXY_CHIL.LENS;i++) { YXXY_BGFA[i].SETP("INFA", YXXY_CHIL.DATA[i][1], YXXY_CHIL.DATA[i][2], YXXY_CHIL.DATA[i][3], YXXY_CHIL.DATA[i][4], YXXY_CHIL.DATA[i][5]); YXXY_BGFA[i].SHOW(); } //-----------------配置复制:按键检测------------------------ YXXY_DQFW.SETP("CONF","POS","YXXY",01,4); YXXY_DQXZ.SETP("CONF","POS","YXXY",02,4); for(int LOOP=1;LOOP<=YXXY_DQFW.LENS;LOOP++) for(int LTMP=1;LTMP<=4;LTMP++) YXXY_XZFW[LOOP][LTMP]=YXXY_DQFW.DATA[LOOP][LTMP]; YXXY_XZFW[ 0][ 0]=YXXY_DQFW.LENS; for(int LOOP=1;LOOP<=YXXY_DQXZ.LENS;LOOP++) for(int LTMP=1;LTMP<=4;LTMP++) YXXY_XZXZ[LOOP][LTMP]=YXXY_DQXZ.DATA[LOOP][LTMP]; YXXY_XZXZ[ 0][ 0]=YXXY_DQXZ.LENS; YXXY_CHIL.SETP("MAPS","MAP","INFA",00,5); //---------------载入图像:复制星星-------------------------- for(int LOOP=1;LOOP<=10;LOOP++) for(int LTMP=1;LTMP<= 3;LTMP++) YXXY_STAR[LOOP][LTMP].SETP("STAR",01,362-87+87*LOOP,572+LTMP*35-35,32,31); //------------------------------------------------------- return 0; } int YXXY_CHOC(int order) { YXXY_DATA.INIT(); SDE CHOC_EVENT; SDL_PollEvent(&CHOC_EVENT); REND_CLEN(); READ CHILD("MAPS","MAP","INFA",order,5); for(int i=1;i<=CHILD.LENS;i++) { YXXY_BGMP[i].SETP("INFA", //配置复制 CHILD.DATA[i][1], CHILD.DATA[i][2], CHILD.DATA[i][3], CHILD.DATA[i][4], CHILD.DATA[i][5]); YXXY_BGMP[i].SHOW(); } while(CHOC_EVENT.type!=SDL_QUIT) { for(int i=1;i<=CHILD.LENS;i++) YXXY_BGMP[i].SHOW(); for(int LOOP=1;LOOP<=10;LOOP++) { for(int LTMP=1;LTMP<=YXXY_DATA.DASX[(order-1)*10+LOOP];LTMP++) YXXY_STAR[LOOP][LTMP].SHOW(); } REND_SHOW(); while (SDL_PollEvent(&CHOC_EVENT)) { if(CHOC_EVENT.type==SDL_QUIT) WIND_EXIT(); //关闭窗口 if(CHOC_EVENT.type==SDL_MOUSEBUTTONUP) { CHOC_EVENT.type=SDL_KEYUP; int YXXY_GXIT= BOTT_DEAL(CHOC_EVENT.button.x, CHOC_EVENT.button.y, YXXY_XZXZ, YXXY_XZXZ[0][0]); //检测按键 if(YXXY_GXIT==0)break; if(YXXY_GXIT==1)return 0; else { int CGRT=1; for(;CGRT==1;) { CGMS GAME; GAME.CGMS_INIT(YXXY_GXIT-2+order*10); CGRT=GAME.CGMS_DEAL(); if (CGRT==2)return 2; if (CGRT==3)break; } } } } } return 0; } int YXXY_INFT() { //------------------------------------------------------- REND_CLEN(); while(YXXY_EVEN.type!=SDL_QUIT) { for(int i=1;i<=YXXY_CHIL.LENS;i++) //渲染背景 YXXY_BGFA[i].SHOW(); REND_SHOW(); //执行渲染 while (SDL_PollEvent(&YXXY_EVEN)) { if(YXXY_EVEN.type==SDL_QUIT) WIND_EXIT(); //关闭窗口 if(YXXY_EVEN.type==SDL_MOUSEBUTTONUP) { int YXXY_XZGQ= //判断点击区域 BOTT_DEAL(YXXY_EVEN.button.x, YXXY_EVEN.button.y, YXXY_XZFW, YXXY_XZFW[0][0]); //关卡界面 if(YXXY_XZGQ==0)break; //无操作 if(YXXY_XZGQ==5)return 0; //返回上一层 YXXY_EVEN.type=SDL_KEYUP; //重置事件，防止段错误 int CGRT=YXXY_CHOC(YXXY_XZGQ); //进入子菜单 if(CGRT==2) return 2; //强制返回 } } } return 0; } 游戏进程CGMS.CPP#pragma once #ifndef CGMS_CPP #define CGMS_CPP #include "LIBS/READ.CPP" #include "LIBS/FKYP.CPP" #include "LIBS/TYPE.CPP" #include "LIBS/REND.CPP" #include "LIBS/FONT.CPP" #include "LIBS/SAVE.CPP" #include "EXTL/WIND.CPP" #include "EXTL/DBUG.CPP" class CGMS { public: REND GAME_REND; //渲染队列 READ CGMS_PACN; //过关背景 READ CGMS_FACN; //失败背景 READ CGMS_PAMG; //过关按钮 FONT CGMS_TIME; //时间文字 FONT CGMS_OUTT; //星级文字 SAVE CGMS_SAVE; //数据存档 int LAST_TIME; //上次时间 int NOWN_TIME; //当前时间 int TOTA_TIME; //总共时间 int GAME_NUMS; //游戏编号 int CGMS_PART; //回调参数 int CGMS_GMPA[16][5];//通关图像 int CGMS_GMFA[16][5];//失败图像 int CGMS_PDAN(int ix,int iy,int FTTL[16][5],int LTNS)//-----------------判断鼠标点击范围----------------- { for(int LOOP=1;LOOP<=LTNS;LOOP++){ //如果在范围内，返回对应数组偏移量，对应CONF配置序列中的ID int PDSJ_FLAG=0; if(ix<FTTL[LOOP][1]||ix>FTTL[LOOP][2]) //横坐标 PDSJ_FLAG=1; if(iy<FTTL[LOOP][3]||iy>FTTL[LOOP][4]) //纵坐标 PDSJ_FLAG=1; if(PDSJ_FLAG==0) return LOOP;} return 0; } int CGMS_INIT(int CGMS_NUMS) //------------------初始化游戏内容------------------ { //------------------配置复制:按键检测------------------------ CGMS_PACN.SETP("CONF","POS","CGMS",01,4); CGMS_FACN.SETP("CONF","POS","CGMS",02,4); CGMS_PAMG.SETP("MAPS","MAP","PASS",00,05); for(int LOOP=1;LOOP<=CGMS_PACN.LENS;LOOP++) for(int LTMP=1;LTMP<=4;LTMP++) CGMS_GMPA[LOOP][LTMP]=CGMS_PACN.DATA[LOOP][LTMP]; CGMS_GMPA[ 0][ 0]=CGMS_PACN.LENS; for(int LOOP=1;LOOP<=CGMS_FACN.LENS;LOOP++) for(int LTMP=1;LTMP<=4;LTMP++) CGMS_GMFA[LOOP][LTMP]=CGMS_FACN.DATA[LOOP][LTMP]; CGMS_GMFA[ 0][ 0]=CGMS_FACN.LENS; //--------------------------------------------------------- GAME_REND.INIT(CGMS_NUMS); LAST_TIME=(int)SDL_GetTicks(); NOWN_TIME=(int)SDL_GetTicks(); GAME_NUMS=CGMS_NUMS; TOTA_TIME=0; CGMS_TIME.SETP(255,255,255, 80, 50,100,50,(char*)"0.00" ,72); CGMS_OUTT.SETP(255,255,255,750,350, 80,40,(char*)"9.99\"",72); return 0; } //----------------------------闯关成功界面实现---------------------------- int CGMS_PASS() { SDE CGMA_PASS_EVEN; //创建事件 int CGMS_PASS_FLAG=1; //循环标识符 IMGS CGMS_PASS_IGPA[16]; //菜单图像 IMGS CGMS_PASS_STAR[4]; //三颗星图像 CGMA_PASS_EVEN.type=SDL_KEYDOWN; //初始化事件 CGMS_TIME.SETP(1,200,100); //显示时间TTF大小重写 CGMS_TIME.SETP(0,650,150); //显示时间TTF位置重写 int CGMS_PASS_SNUM= //获取等级 CGMS_SAVE.EXPO(GAME_NUMS-9,TOTA_TIME); if(CGMS_PASS_SNUM>CGMS_SAVE.DASX[GAME_NUMS-9]){ //等级打破纪录 CGMS_SAVE.DASX[GAME_NUMS-9]=CGMS_PASS_SNUM; //更新等级 CGMS_SAVE.WRIT();} //数据存盘 if(CGMS_SAVE.PDDP(GAME_NUMS-9,TOTA_TIME)==true){ //时间打破纪录 CGMS_SAVE.DAPX[GAME_NUMS-9]=TOTA_TIME; //更新时间 CGMS_SAVE.WRIT();} //数据存盘 for (int LOOP=1;LOOP<= 3;LOOP++) //载入星星 CGMS_PASS_STAR[LOOP].SETP("STAR", 00,548+LOOP*73,279,57,54); for (int LOOP=1;LOOP<=CGMS_PAMG.LENS;LOOP++) //载入背景 CGMS_PASS_IGPA[LOOP].SETP("MENU", //编号 CGMS_PAMG.DATA[LOOP][1], //类型 CGMS_PAMG.DATA[LOOP][2], //水平 CGMS_PAMG.DATA[LOOP][3], //垂直 CGMS_PAMG.DATA[LOOP][4], //宽度 CGMS_PAMG.DATA[LOOP][5]); //高度 while(CGMS_PASS_FLAG)//--------------------CGMS_PASS主体循环--------------------- { STR STRS_TEMP; //三星时间 STR STTM_TEMP; //实际时间 REND_CLEN(); //清空渲染 for (int LOOP=1;LOOP<=CGMS_PAMG.LENS;LOOP++) //显示背景 CGMS_PASS_IGPA[LOOP].SHOW(); if(CGMS_PASS_SNUM>0) for (int LOOP=1;LOOP<=CGMS_PASS_SNUM;LOOP++) //显示星级 CGMS_PASS_STAR[LOOP].SHOW(); STRS_TEMP =to_string(TOTA_TIME/1000)+ //时间字体 STTM_TEMP =to_string(CGMS_SAVE.DARX[GAME_NUMS-9][3]/1000) //三星字体 +"."+to_string(CGMS_SAVE.DARX[GAME_NUMS-9][3]%1000/10)+"\""; CGMS_TIME.SETP((char*)STRS_TEMP.c_str()); //设置时间 CGMS_OUTT.SETP((char*)STTM_TEMP.c_str()); //设置三星 CGMS_OUTT.SHOW(); //显示三星 CGMS_TIME.SHOW(); //显示时间 REND_SHOW(); while (SDL_PollEvent(&CGMA_PASS_EVEN))//------------事件处理循环-------------- { if(CGMA_PASS_EVEN.type==SDL_QUIT){ CGMS_PASS_FLAG=0; WIND_EXIT();} //退出程序 if(CGMA_PASS_EVEN.type==SDL_MOUSEBUTTONUP){ //按下鼠标 int CGMS_ANPA= CGMS_PDAN(CGMA_PASS_EVEN.button.x, //鼠标-Y轴 CGMA_PASS_EVEN.button.y, //鼠标-X轴 CGMS_GMPA, //传入数组 CGMS_GMPA[0][0]); //区域长度 if(CGMS_ANPA==0){CGMS_ANPA=-1;break;} //无效点击 else{ CGMS_PART=CGMS_ANPA; //回传参数 return CGMS_ANPA;}} } }//----------------------------------------------------------------------------- return 0; } int CGMS_FAIL(int DQJD) { SDE CGMS_FAIL_EVEN; while (SDL_PollEvent(&CGMS_FAIL_EVEN)) CGMS_FAIL_EVEN.type=SDL_KEYUP; IMGS FAIM[7]; FAIM[1].SETP("FAIL",01,560,580,457,175); FAIM[2].SETP("FAIL",02,780,650,197, 85); FAIM[3].SETP("FAIL",03,575+DQJD,590, 23, 22); FAIM[4].SETP("MENU",12,590,650, 85, 85); FAIM[5].SETP("MENU",13,685,650, 85, 85); FAIM[6].SETP("MENU",21,640,150,300,150); while(CGMS_FAIL_EVEN.type!=SDL_QUIT) { for(int LOOP=1;LOOP<=6;LOOP++) FAIM[LOOP].SHOW(); REND_SHOW(); while (SDL_PollEvent(&CGMS_FAIL_EVEN)) { if(CGMS_FAIL_EVEN.type==SDL_QUIT) { WIND_EXIT(); //关闭窗口 break; } if(CGMS_FAIL_EVEN.type==SDL_MOUSEBUTTONUP) { CGMS_FAIL_EVEN.type=SDL_KEYUP; int CGMS_ANPA= CGMS_PDAN(CGMS_FAIL_EVEN.button.x, CGMS_FAIL_EVEN.button.y, CGMS_GMFA, CGMS_GMFA[0][0]); //关卡界面 if(CGMS_ANPA==0) { CGMS_ANPA=-1; break; } else { CGMS_PART=CGMS_ANPA; return CGMS_ANPA; } } } } return 0; } int CGMS_SHOW() { int SHOW_TEMP; STR STRS_TEMP; int RTEN=GAME_REND.EXEC(); GAME_REND.SHOW(); CGMS_TIME.SHOW(); if(RTEN== 0)//过关 { SHOW_TEMP=CGMS_PASS(); return SHOW_TEMP; } if(RTEN== 1)//计时 { NOWN_TIME =SDL_GetTicks(); if(NOWN_TIME-LAST_TIME>10) { TOTA_TIME+=NOWN_TIME-LAST_TIME; LAST_TIME =NOWN_TIME; } if(DBUG_OTIME==1) { cout<<" [CGMS] "; DBUG_GTIM(); cout<<"0x"<<WIND_RENDP<<" "<<"GAME_PROEXE: "<<"~~|GAME|NOW_TIME_IS:"; printf("%6.2f\n",(float)TOTA_TIME/1000); } } if(RTEN==-1)//暂停 { NOWN_TIME =SDL_GetTicks(); LAST_TIME =NOWN_TIME; } STRS_TEMP =to_string(TOTA_TIME/1000)+"."+to_string(TOTA_TIME%1000/10); CGMS_TIME.SETP((char*)STRS_TEMP.c_str()); CGMS_TIME.SHOW(); REND_SHOW(); return 0; } int CGMS_NEXT() { if(DBUG_OTSTP==1) { cout<<" [NEXT] "; DBUG_GTIM(); cout<<"0x"<<WIND_RENDP <<" "<<"NEXT_BIRDNS: " <<"~~|BIRD|NOW_BIRD_AT:" <<GAME_REND.NOWN+GAME_REND.BIRP <<endl; } if( GAME_REND.MAPS[GAME_REND.NOWN+GAME_REND.BIRP-1].NOWH> GAME_REND.MAPS[GAME_REND.NOWN+GAME_REND.BIRP ].NOWH+10) return 1; if( GAME_REND.BIRP<=7 ||GAME_REND.TEMP.LENS- (GAME_REND.NOWN+ GAME_REND.BIRP)<=6) GAME_REND.BIRP++; else GAME_REND.NOWN=GAME_REND.NOWN+1; return 0; } int CGMS_DEAL() { int DEAL_EXIT=1; int DEAL_CGRT; SDE DEAL_EVEN; while(DEAL_EXIT) { while (SDL_PollEvent(&DEAL_EVEN)) { if(DEAL_EVEN.type==SDL_QUIT)WIND_EXIT(); //关闭窗口 if(DEAL_EVEN.type==SDL_MOUSEBUTTONDOWN ||DEAL_EVEN.type==SDL_KEYDOWN) { if(CGMS_NEXT()==1&&DBUG_NOKIL == 0){ DEAL_CGRT = CGMS_FAIL((int) (GAME_REND.NOWN+ GAME_REND.BIRP) /GAME_REND.TEMP.LENS*350); //小鸟相撞 if(DEAL_CGRT==3){ TOTA_TIME=0; int LOOP=GAME_REND.NOWN+GAME_REND.BIRP-1; for(;LOOP>=2&&GAME_REND.MAPS[LOOP].TYPE>10;LOOP--); GAME_REND.BIRP=1; GAME_REND.NOWN=LOOP;} else return DEAL_CGRT;} } } DEAL_CGRT = CGMS_SHOW(); if (DEAL_CGRT!=0)return DEAL_CGRT; SDL_Delay(16); } return 0; } }; #endif 调试模式：DBUG.CPP#pragma once #ifndef DBUG_CPP #define DBUG_CPP #include "HEAD.CPP" #include "windows.h" int DBUG_INIT(int DBUG_INIT_ARGC, char* DBUG_INIT_ARGV[])//初始化调试模式，检测外部参数，设置渲染模式 { system("mode con:cols=79 lines=60"); if(DBUG_INIT_ARGC>=2)for (int DBUG_INIT_LOOP=1;DBUG_INIT_LOOP<DBUG_INIT_ARGC;DBUG_INIT_LOOP++) { if(DBUG_INIT_ARGV[DBUG_INIT_LOOP][1]=='a'||DBUG_INIT_ARGV[DBUG_INIT_LOOP][1]=='A')DBUG_ACCED = 0; if(DBUG_INIT_ARGV[DBUG_INIT_LOOP][1]=='b'||DBUG_INIT_ARGV[DBUG_INIT_LOOP][1]=='B')DBUG_SYNCD = 0; if(DBUG_INIT_ARGV[DBUG_INIT_LOOP][1]=='c'||DBUG_INIT_ARGV[DBUG_INIT_LOOP][1]=='C')DBUG_NOKIL = 1; if(DBUG_INIT_ARGV[DBUG_INIT_LOOP][1]=='d'||DBUG_INIT_ARGV[DBUG_INIT_LOOP][1]=='D')DBUG_DEBUG = 1; if(DBUG_INIT_ARGV[DBUG_INIT_LOOP][1]=='e'||DBUG_INIT_ARGV[DBUG_INIT_LOOP][1]=='E')DBUG_EEOOR = 1; if(DBUG_INIT_ARGV[DBUG_INIT_LOOP][1]=='f'||DBUG_INIT_ARGV[DBUG_INIT_LOOP][1]=='F')DBUG_OTFPS = 1; if(DBUG_INIT_ARGV[DBUG_INIT_LOOP][1]=='g'||DBUG_INIT_ARGV[DBUG_INIT_LOOP][1]=='G')DBUG_OTIME = 1; if(DBUG_INIT_ARGV[DBUG_INIT_LOOP][1]=='h'||DBUG_INIT_ARGV[DBUG_INIT_LOOP][1]=='H')DBUG_OTSTP = 1; } if(DBUG_ACCED ==0 ) DBUG_GUPMD-=2; if(DBUG_SYNCD ==0 ) DBUG_GUPMD-=4; if(DBUG_DEBUG)cout<<"--------------------------------DEBUG MODE ON--------------------------------"<<endl; else cout<<"--------------------------------DEBUG MODE OFF-------------------------------"<<endl; return 0; } int DBUG_GTIM() //---------------输出当前时间---------------- { time_t DBUG_OUTP_TIMP; time(&DBUG_OUTP_TIMP); char DBUG_OUTP_TIME[64]; strftime(DBUG_OUTP_TIME, sizeof(DBUG_OUTP_TIME), "%Y-%m-%d %H:%M:%S", localtime(&DBUG_OUTP_TIMP) ); cout<<DBUG_OUTP_TIME<<" "; return 0; } int DBUG_OUTP(void* DBUG_OUTP_PTRP,// string DBUG_OUTP_NAME, string DBUG_OUTP_TEXT) { if(DBUG_DEBUG ==0 && DBUG_EEOOR==0) return 0; if(DBUG_OUTP_PTRP!=nullptr && DBUG_DEBUG==0) return 0; if(DBUG_OUTP_PTRP!=nullptr && DBUG_DEBUG==1) cout<<" [OKAY] "; else cout<<" [FAIL] "; DBUG_GTIM(); cout<<"0x"<<DBUG_OUTP_PTRP; cout<<DBUG_OUTP_NAME<<": "; cout<<DBUG_OUTP_TEXT<<endl; return 0; } int DBUG_TFPS(int DBUG_TFPS_NFPS,const string DBUG_OUTP_NAME,const string DBUG_OUTP_TEXT) { if(DBUG_OTFPS==0) return 0; if(DBUG_TFPS_NFPS>=30)cout<<" [INFO] "; else cout<<" [WARN] "; DBUG_GTIM(); cout<<"0x"<<WIND_RENDP<<DBUG_OUTP_NAME<<": "<<DBUG_TFPS_NFPS<<DBUG_OUTP_TEXT<<endl; return 0; } #endif 头文件EXTL/HEAD.CPP#pragma once #ifndef HEAD_CPP #define HEAD_CPP #include <iostream> #include <string> #include "SDL.h" #include "SDL_image.h" #include "SDL_ttf.h" #include <time.h> #define STR string #define STP SDL_Texture* #define SDP SDL_Rect #define SDE SDL_Event #define SDR SDL_Renderer #define SDS SDL_Surface #define SDW SDL_Window #define SDC SDL_Color #define SDA SDL_AudioSpec #define TFT TTF_Font #define TFO TTF_OpenFont using namespace std; static SDR* WIND_RENDP = nullptr; //渲染指针 static SDW* WIND_WINDP = nullptr; //窗口指针 static const char* WIND_TITLE = "No Jumping"; //菜单标题 static const int WIND_WIDTH = 1500; //水平大小 static const int WIND_HEIGH = 750; //垂直大小 static const int GAME_MAXHT = 450; //方块上限 static const int GAME_MINHT = 750; //方块下限 static int DBUG_GUPMD = 0x00000006; //渲染模式 static int DBUG_ACCED = 1; //A显卡加速 static int DBUG_SYNCD = 1; //B垂直同步 static int DBUG_NOKIL = 0; //C作弊模式 static int DBUG_DEBUG = 0; //D调试模式 static int DBUG_EEOOR = 1; //E输出错误 static int DBUG_OTFPS = 0; //F输出帧率 static int DBUG_OTIME = 0; //G输出时间 static int DBUG_OTSTP = 0; //H输出步数 #endif 窗口控制WIND.CPP#pragma once #ifndef WIND_CPP #define WIND_CPP #include"HEAD.CPP" #include"DBUG.CPP" int WIND_INIT(int DBUG_INIT_ARGC,char** DBUG_INIT_ARGV) { /*------------------------------创建窗口------------------------------*/ DBUG_INIT(DBUG_INIT_ARGC,DBUG_INIT_ARGV); if(SDL_Init(SDL_INIT_VIDEO)<0) return -1; WIND_WINDP=SDL_CreateWindow(WIND_TITLE, //窗口标题 SDL_WINDOWPOS_UNDEFINED,//垂直位置 SDL_WINDOWPOS_UNDEFINED,//水平位置 WIND_WIDTH, //窗口宽度 WIND_HEIGH, //窗口高度 SDL_WINDOW_SHOWN //显示窗口 ); DBUG_OUTP(WIND_WINDP," LOAD_WINDOW","WIND_WINDP");//输出调试信息 srand((unsigned)time(nullptr)); //随机种子生成 TTF_Init(); //字体初始化 return 0; } int WIND_EXIT() { /*------------------------------退出程序------------------------------*/ SDL_DestroyRenderer(WIND_RENDP); //销毁渲染 SDL_DestroyWindow(WIND_WINDP); //销毁窗口 SDL_Quit(); //退出GUI system("taskkill /IM 奔跑吧*"); //销毁进程 system("taskkill /IM JUM* "); //销毁进程 system("taskkill /IM GAM* "); //销毁进程 system("EXIT.CMD"); //销毁进程 exit(0); //退出程序 return 0; } #endif 游戏库文件：【点击下载】