我正在克隆一只松鸡。我表现得很好:每秒60帧。当时它只有一根柱子/障碍物。我一加上3个,fps就降到了30及以下。那么游戏现在就不能玩了。我知道这与一直在做repaint()
有关。
以下是代码:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
/**
* Created by Lazar on 25/05/15.
*/
public class Environment extends JComponent implements ActionListener {
public static final Dimension dimension = new Dimension(800,600);
BufferedImage img;
BufferedImage ptica1;
BufferedImage ptica2;
double skokbrojac = 0;
int brzina = 4; // speed // MUST Background % brzina = 0
int dx;
int dx2;
int pad = 0; //drop
Timer timer;
boolean parno;
boolean skok = false;
//Stubovi // Pillars
Stub stub1 = new Stub();
Stub stub2 = new Stub();
Stub stub3 = new Stub();
ArrayList<Stub>stubovi = new ArrayList<Stub>();
int razmakStub; // Space between pillars
public Environment() {
setPreferredSize(dimension);
img = Util.openImage("pozadina.png");
ptica1 = Util.openImage("ptica1.png");
ptica2 = Util.openImage("ptica2.png");
stubovi.add(stub1);
stubovi.add(stub2);
stubovi.add(stub3);
dx = img.getWidth()/2;
timer = new Timer(1000/60,this);
timer.start();
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
super.mousePressed(e);
skok = true; // start jump
skokbrojac = 0; //jump frame counter
}
});
}
protected void paintComponent(Graphics g){
Graphics2D g2d = (Graphics2D)g;
//g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
if(dx == img.getWidth()){ //image horizontal scroll
dx2 = 0;
}
if(dx2 == img.getWidth()/2){ //image horizontal scroll
dx = dimension.width;
}
g2d.drawImage(img,getWidth() - dx, 0, null); //draw background
if(dx >= img.getWidth()){
g2d.drawImage(img,getWidth() - dx2, 0, null);
}
if(parno){
g2d.drawImage(ptica1,dimension.width/2, 290 + pad, null); //draw bird
}
else{
g2d.drawImage(ptica2,dimension.width/2, 290 + pad, null); //draw bird
}
stub1.postoji = true; //pillar1 exists?
if(razmakStub > 240){
stub2.postoji = true;
}
if(razmakStub > 480){ //pillar1 exists?
stub3.postoji = true;
}
for(Stub i : stubovi){ //draw pillars if they exist
if(i.postoji)
i.crtaj(g2d);
}
}
@Override
public void actionPerformed(ActionEvent e) {
dx = dx + brzina;
dx2 = dx2 + brzina;
if(skokbrojac > 5) // jump frame lenght
skok = false;
if(skok){
pad -= 15; // jump height
}
else{
pad += 8; //rate of the fall
}
skokbrojac++;
parno ^= true; // for different bird images
if(290 + pad >= 536 || 290 + pad<= 3) //border hit detect
timer.stop();
razmakStub += brzina;
for(Stub i : stubovi){ //reset pillars and make them move
if(i.postoji){
if(i.getDx() < -50){
i.setDx(800);
i.randomDy();
}
i.setDx(i.getDx() - brzina);
}
}
repaint();
}
}
完整的项目来源
还要记住这是真正的未抛光版本,所以代码很难看。我正在寻找提升性能的解决方案。
主类:
import javax.swing.*;
/**
* Created by Lazar on 25/05/15.
*/
public class Main {
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Frame(new Environment());
}
});
}
}
框架类别:
import javax.swing.*;
/**
* Created by Lazar on 25/05/15.
*/
public class Frame extends JFrame{
public Frame(JComponent content){
setContentPane(content);
setTitle("Flappy");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(getPreferredSize());
setResizable(false);
setVisible(true);
setLocationRelativeTo(null);
}
}
支柱/支柱类:
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
/**
* Created by Lazar on 26/05/15.
*/
public class Stub {
BufferedImage dole;
BufferedImage gore;
Random r = new Random();
int dx = 700;
int dy = r.nextInt(250) + 250;
boolean postoji = false;
public void crtaj(Graphics2D g2d){
dole = Util.openImage("stub_dole.png");
gore = Util.openImage("stub_gore.png");
g2d.drawImage(dole, dx, dy, null);
g2d.drawImage(gore, dx, -(560-dy), null);
}
public void setDx(int dx) {
this.dx = dx;
}
public void randomDy(){
this.dy = r.nextInt(250) + 250;
}
public int getDx() {
return dx;
}
}
Ptica/Brid等级:
import java.awt.Graphics;
import java.awt.image.BufferedImage;
/**
* Created by Lazar on 26/05/15.
*/
public class Ptica {
BufferedImage ptica1;
BufferedImage ptica2;
boolean ptica;
boolean skok = false;
int pad = 0;
double skokBrojac = 0;
public Ptica(){
ptica1 = Util.openImage("/slike/ptica1.png");
ptica2 = Util.openImage("/slike/ptica2.png");
}
public void crtajPticu(Graphics g2d){
ptica ^= true;
if(ptica){
g2d.drawImage(ptica1, Environment.dimension.width/2, Environment.dimension.height/2-110 + pad, null);
}
else{
g2d.drawImage(ptica2, Environment.dimension.width/2, Environment.dimension.height/2-110 + pad, null);
}
System.out.println(pad);
}
public void setSkok(boolean skok) {
this.skok = skok;
}
public void setSkokBrojac(double skokBrojac) {
this.skokBrojac = skokBrojac;
}
public double getSkokBrojac() {
return skokBrojac;
}
public boolean isSkok() {
return skok;
}
public void setPad(int pad) {
this.pad = pad;
}
public int getPad() {
return pad;
}
}
Util类:
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
/**
* Created by Lazar on 25/05/15.
*/
public class Util {
public static BufferedImage openImage(String name){
try {
if(!name.startsWith("/slike/")){
name="/slike/"+name;
}
return ImageIO.read(Util.class.getResource(name));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
正如@alex fitzpatrick所建议的,评测总是好的。也:
Util创建的图像类型。openImage
调用是否与您绘制的graphics2D对象兼容?你可能会花一些时间进行转换(图像类型)
getWidth()
等的调用。在对象初始化后,您知道这些值,请缓存它们
repaint
。使用指定要重新绘制区域的重载版本
使用探查器确定代码实际花费的时间(请注意,YourKit有15天的免费试用许可证)。
一旦你知道你的瓶颈是什么,然后确定是否有一个简单的解决方案,如果没有,考虑更好的算法和数据结构,以减少代码的算法复杂性。
例如,从您的Stub类中,您可以执行以下操作。。。
public void crtaj(Graphics2D g2d){
dole = Util.openImage("stub_dole.png");
gore = Util.openImage("stub_gore.png");
g2d.drawImage(dole, dx, dy, null);
g2d.drawImage(gore, dx, -(560-dy), null);
}
加载图像可能需要时间。你应该有一个“cache”类来管理它们(加载一次),或者在创建存根
类时加载它们(我更喜欢cache类,就像你创建和销毁许多存根
一样,加载存根
类(例如构造函数)中的资源可能会成为一个瓶颈
例如,通过使用可重用的对象缓存(而是重新创建对象并重新加载它们的资源),它能够从200-300个对象同时移动到4000多个对象
我们都知道MMO游戏的流行趋势。玩家面对面直播。 我关心的领域是玩家移动和游戏结果的存储。 通过NPGSQL适配器使用Csharp和PostgreSql v9.0 游戏客户端是基于浏览器的ASP.NET并调用所有与数据库相关的处理 为了理解我的查询,请考虑以下场景 我们将游戏进度存储在postgres表中。 例如,锦标赛从四名玩家开始,并遵循以下活动 < li >每个玩家从100点生命值开始 <
目前,我正在尝试用Java开发基于2D平铺的侧滚游戏,主要基于David Brackeen的“用Java开发游戏”中的代码和示例 目前地图文件的大小为100x100个图块(每个图块为64x64像素)。我已经将系统配置为仅显示玩家可见的图块。Graphics系统由ScreenManager类管理,该类返回当前BufferStrategy的图形对象,如下所示: ScreenManager.java 来
我在java中创建了一个2D游戏,并试图将其分辨率提高到60 fps,分辨率为1920x1080像素。我的游戏逻辑在不到1毫秒的时间内表现良好。但是绘图需要超过10毫秒。在我相当强大的台式机(英特尔i5-4670K@3.40Ghz)上这可能就足够了,但是在我的笔记本电脑(英特尔i5-6300HQ@2.30Ghz)上,游戏已经慢了很多。绘图分为两个主要步骤: > 将游戏的每个部分绘制到Buffere
PS Vita上可游玩存储于PlayStaiton®Vita卡或从PlayStation®Store下载的游戏。 游戏的LiveArea™ 游玩PlayStaiton®Vita卡的游戏 游玩从PlayStation®Store下载的游戏 将使用PS3™下载的游戏复制至PS Vita游玩 在PS Vita游玩PSP™ (PlayStation®Portable)的游戏
我已经停止编程一段时间了。大概4年左右,我只是想搞乱它,所以我决定做一个高:低数字猜谜游戏。(猜一个数字1-100,如果你猜得太高或太低,程序会说)我完全忘了我该怎么做:
包含在程序启动时启动的线程。这个线程包含一个循环,每40毫秒更新一次游戏并重新绘制()board。 备选办法B: 板创建一个摆动计时器。这个计时器的动作监听器是板本身。actionPerformed()方法每40毫秒运行一次,并更新game+repaints Board()。 谢谢