- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在为学校组织一个小项目,其中涉及渲染元素周期表。我选择使用 LWJGL 来做到这一点。然而,问题是,当我渲染表格时,游戏以 ~30fps(上限为 60fps)开始,并迅速波动到个位数 fps。我相信问题可能是内存泄漏,但我不确定。任何人都可以看到我的代码有任何明显的问题吗?以下是渲染表格涉及的主要类:
EntityPeriodicTable:负责保存大量 EntityElement 对象(见下文),激活它们的逻辑(tick() 和 updateInput())。 包 com.flafla2.periodicTable;
import org.lwjgl.opengl.GL11;
public class EntityPeriodicTable extends ClickableEntity { //ClickableEntity is an abstract class in charge of the tick(), updateInput(), and render() methods, as well as positioning
public EntityElement[] elements = {//This is unfinished, but you get the idea.
//new EntityElement(Atomic #, State, Metal, "Symbol", "Name", new Vector2D(posx,posy), this)
new EntityElement(1, 2, 2, "H", "Hydrogen", new Vector2D(1,1), this),
new EntityElement(2, 2, 2, "He", "Helium", new Vector2D(18,1), this),
new EntityElement(3, 0, 0, "Li", "Lithium", new Vector2D(1,2), this),
new EntityElement(4, 0, 0, "Be", "Beryllium", new Vector2D(2,2), this),
new EntityElement(5, 0, 1, "B", "Boron", new Vector2D(13,2), this),
new EntityElement(6, 0, 2, "C", "Carbon", new Vector2D(14,2), this),
new EntityElement(7, 2, 2, "N", "Nitrogen", new Vector2D(15,2), this),
new EntityElement(8, 2, 2, "O", "Oxygen", new Vector2D(16,2), this),
new EntityElement(9, 2, 2, "F", "Fluorine", new Vector2D(17,2), this),
new EntityElement(10,2, 2, "Ne", "Neon", new Vector2D(18,2), this),
new EntityElement(11, 0, 0, "Na", "Sodium", new Vector2D(1,3), this),
new EntityElement(12, 0, 0, "Mg", "Magnesium", new Vector2D(2,3), this),
new EntityElement(13, 0, 0, "Al", "Aluminum", new Vector2D(13,3), this),
new EntityElement(14, 0, 1, "Si", "Silicon", new Vector2D(14,3), this),
new EntityElement(15, 0, 2, "P", "Phosphorous", new Vector2D(15,3), this),
new EntityElement(16, 0, 2, "S", "Sulfur", new Vector2D(16,3), this),
new EntityElement(17, 2, 2, "Cl", "Chlorine", new Vector2D(17,3), this),
new EntityElement(18, 2, 2, "Ar", "Argon", new Vector2D(18,3), this),
new EntityElement(19, 0, 0, "K", "Potassium", new Vector2D(1,4), this),
new EntityElement(20, 0, 0, "Ca", "Calcium", new Vector2D(2,4), this),
new EntityElement(21, 0, 0, "Sc", "Scandium", new Vector2D(3,4), this),
new EntityElement(22, 0, 0, "Ti", "Hydrogen", new Vector2D(4,4), this),
new EntityElement(23, 0, 0, "V", "Hydrogen", new Vector2D(5,4), this),
new EntityElement(24, 0, 0, "Cr", "Hydrogen", new Vector2D(6,4), this),
new EntityElement(25, 0, 0, "Mn", "Hydrogen", new Vector2D(7,4), this),
new EntityElement(26, 0, 0, "Fe", "Hydrogen", new Vector2D(8,4), this),
new EntityElement(27, 0, 0, "Co", "Hydrogen", new Vector2D(9,4), this),
new EntityElement(28, 0, 0, "Ni", "Hydrogen", new Vector2D(10,4), this),
new EntityElement(29, 0, 0, "Cu", "Hydrogen", new Vector2D(11,4), this),
new EntityElement(30, 0, 0, "Zn", "Hydrogen", new Vector2D(12,4), this),
new EntityElement(31, 0, 0, "Ga", "Hydrogen", new Vector2D(13,4), this),
new EntityElement(32, 0, 1, "Ge", "Hydrogen", new Vector2D(14,4), this),
new EntityElement(33, 0, 1, "As", "Hydrogen", new Vector2D(15,4), this),
new EntityElement(34, 0, 2, "Se", "Hydrogen", new Vector2D(16,4), this),
new EntityElement(35, 1, 2, "Br", "Hydrogen", new Vector2D(17,4), this),
new EntityElement(36, 2, 2, "Kr", "Hydrogen", new Vector2D(18,4), this),
};
public final int ELEMENT_SIZE = 40;
public Vector2D mousePos = new Vector2D(0,0); //Simple 2D vector struct.
public double[] SOLID_RGB = {0,0,0};
public double[] LIQUID_RGB = {0,0,1};
public double[] GAS_RGB = {1,0,0};
public double[] METAL_RGB;
public double[] NONMETAL_RGB;
public double[] METALLOID_RGB;
public double[] RECENT_RGB;
public EntityPeriodicTable(Vector2D pos) {
this.pos = pos;
METAL_RGB = new double[3];
METAL_RGB[0] = 0.596078431; //152/255
METAL_RGB[1] = 0.984313725; //251/255
METAL_RGB[2] = 0.596078431; //152/255
NONMETAL_RGB = new double[3];
NONMETAL_RGB[0] = 1;
NONMETAL_RGB[1] = 0.647058824; //165/255
NONMETAL_RGB[2] = 0;
METALLOID_RGB = new double[3];
METALLOID_RGB[0] = 0.866666667; //221/255
METALLOID_RGB[1] = 0.62745098; //160/255
METALLOID_RGB[2] = 0.866666667; //221/255
RECENT_RGB = new double[3];
RECENT_RGB[0] = 0.803921569; //205/255
RECENT_RGB[1] = 0.788235294; //201/255
RECENT_RGB[2] = 0.788235294; //201/255
}
@Override
void render() {
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glDisable(GL11.GL_BLEND);
for(int x=0;x<elements.length;x++)
elements[x].render();
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_BLEND);
for(int x=0;x<elements.length;x++)
elements[x].renderWithTex();
}
@Override
void tick() {
for(int x=0;x<elements.length;x++)
elements[x].tick();
}
@Override
public void updateInput(Vector2D mousePos)
{
this.mousePos = mousePos;
for(int x=0;x<elements.length;x++)
{
if(mousePos.isInBoundsWithDim(elements[x].pos.x, elements[x].pos.y, elements[x].dim.x, elements[x].dim.y))
elements[x].isSelected = true;
else
elements[x].isSelected = false;
}
}
@Override
void onEntityClicked() {
for(int x=0;x<elements.length;x++)
{
if(mousePos.isInBoundsWithDim(elements[x].pos.x, elements[x].pos.y, elements[x].dim.x, elements[x].dim.y))
elements[x].onEntityClicked();
}
}
}
EntityElement:保存表格中特定元素的数据,并进行渲染(渲染代码未完成)
package com.flafla2.periodicTable;
import org.lwjgl.opengl.GL11;
public class EntityElement extends ClickableEntity {
String symbol;
String element;
int atomicNumber;
EntityPeriodicTable table;
int state;//0=solid, 1=liquid, 2=gas
int metalState;//0=metal, 1=metalloid, 2=nonmetal, 3=discovered recently
Vector2D gridPos;
public EntityElement(int an, int st, int ms, String sy, String en, Vector2D gp, EntityPeriodicTable pt)
{
symbol = sy;
element = en;
atomicNumber = an;
table = pt;
state = st;
metalState = ms;
gridPos = gp;
dim.x = table.ELEMENT_SIZE; dim.y = table.ELEMENT_SIZE;
pos.x = table.pos.x + table.ELEMENT_SIZE*(gridPos.x-1); pos.y = table.pos.y + table.ELEMENT_SIZE*(gridPos.y-1);
}
public double[] getStateColor()
{
switch(state)
{
case 0:
return table.SOLID_RGB;
case 1:
return table.LIQUID_RGB;
case 2:
return table.GAS_RGB;
default:
double[] d = {0.0d,0.0d,0.0d};
return d;
}
}
public double[] getMetalColor()
{
switch(metalState)
{
case 0:
return table.METAL_RGB;
case 1:
return table.METALLOID_RGB;
case 2:
return table.NONMETAL_RGB;
case 3:
return table.RECENT_RGB;
default:
double[] d = {0.0d,0.0d,0.0d};
return d;
}
}
@Override
void render() {
GL11.glPushMatrix();
GL11.glTranslatef(pos.x, pos.y, 0);
double[] d = getMetalColor();
GL11.glColor3d(d[0], d[1], d[2]);
GL11.glBegin(GL11.GL_QUADS);
{
GL11.glVertex2f(0, 0);//topleft
GL11.glVertex2f(dim.x, 0);//topright
GL11.glVertex2f(dim.x, dim.y);//bottomright
GL11.glVertex2f(0, dim.y);//bottomleft
}
GL11.glEnd();
GL11.glColor3d(1.0d, 1.0d, 1.0d);
GL11.glPopMatrix();
}
public void renderWithTex()
{
Font.drawString(symbol, new Vector2D(pos.x+dim.x/2-Font.getStringWidth(symbol,2)/2,pos.y+dim.y/2-Font.FONT_HEIGHT), 2);
}
@Override
void tick() {
if(isSelected)
{
dim.x = table.ELEMENT_SIZE+6; dim.y = table.ELEMENT_SIZE+6;
pos.x = table.pos.x + table.ELEMENT_SIZE*(gridPos.x-1)-3; pos.y = table.pos.y + table.ELEMENT_SIZE*(gridPos.y-1)-3;
} else
{
dim.x = table.ELEMENT_SIZE; dim.y = table.ELEMENT_SIZE;
pos.x = table.pos.x + table.ELEMENT_SIZE*(gridPos.x-1); pos.y = table.pos.y + table.ELEMENT_SIZE*(gridPos.y-1);
}
}
@Override
void onEntityClicked() {
}
}
字体:处理屏幕上的渲染文本:
package com.flafla2.periodicTable;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import org.lwjgl.opengl.GL11;
public class Font {
public static final String fontText = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789:;?!\"&',-.[]#()+ ";
public static final BufferedImage fontSheet = TextureLoader.loadTexture("/res/text.png");
public static final int FONT_WIDTH = 9;
public static final int FONT_HEIGHT = 8;
public static void drawString(String s, Vector2D pos, float dim)
{
drawString(s,pos,new Vector2D((int)Math.floor(dim*FONT_WIDTH),(int)Math.floor(dim*FONT_HEIGHT)));
}
public static void drawString(String s, Vector2D pos)
{
drawString(s,pos,new Vector2D(9,8));
}
public static void drawString(String s, Vector2D pos, Vector2D dim)
{
for(int x=0;x<s.length();x++)
{
drawLetter(s.charAt(x),new Vector2D(pos.x+dim.x*x,pos.y),dim);
}
}
public static int getStringWidth(String s)
{
return s.length()*FONT_WIDTH;
}
public static int getStringWidth(String s,float f)
{
return (int)Math.floor(s.length()*FONT_WIDTH*f);
}
public static Vector2D getPosOfLetterOnImg(Character c,int gridNumb)
{
int xOffset = 0;
int yOffset = 0;
if(!c.equals(' '))
{
int letterNumb = fontText.indexOf(c);
xOffset = (letterNumb%26)*FONT_WIDTH;
if(xOffset != 0)
xOffset -=1;
yOffset = 0;
int yGridOffset = (letterNumb < 26) ? 0 : ((letterNumb < 52) ? 1 : 2);
switch(gridNumb)
{
case 1:
yOffset = 34;
break;
case 2:
yOffset = 69;
break;
default:
yOffset = 0;
}
for(int x=0;x<yGridOffset;x++)
yOffset += FONT_HEIGHT+x+3;
} else
{
xOffset = 235;
yOffset = 92;
}
return new Vector2D(xOffset,yOffset);
}
public static void drawLetter(Character c, Vector2D pos, Vector2D dim)
{
if(fontSheet == null)
return;
Vector2D letterPos = getPosOfLetterOnImg(c,2);
BufferedImage letterImage = fontSheet.getSubimage(letterPos.x, letterPos.y, FONT_WIDTH, FONT_HEIGHT);
int textureID = TextureLoader.loadGLTexture(letterImage);
letterImage = null;
GL11.glPushMatrix();
GL11.glTranslatef(pos.x, pos.y, 0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
GL11.glBegin(GL11.GL_QUADS);
{
GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(0, 0);
GL11.glTexCoord2f(1, 0);
GL11.glVertex2f(dim.x, 0);
GL11.glTexCoord2f(1, 1);
GL11.glVertex2f(dim.x, dim.y);
GL11.glTexCoord2f(0, 1);
GL11.glVertex2f(0, dim.y);
}
GL11.glEnd();
GL11.glPopMatrix();
}
}
TextureLoader:加载纹理(呵呵)
package com.flafla2.periodicTable;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.ByteBuffer;
import javax.imageio.ImageIO;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
public class TextureLoader {
public static BufferedImage loadTexture(String texturePath)
{
try {
return ImageIO.read(PeriodicTable.class.getResource(texturePath));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
private static final int BYTES_PER_PIXEL = 4;
public static int loadGLTexture(BufferedImage image){
int[] pixels = new int[image.getWidth() * image.getHeight()];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * BYTES_PER_PIXEL); //4 for RGBA, 3 for RGB
for(int y = 0; y < image.getHeight(); y++){
for(int x = 0; x < image.getWidth(); x++){
int pixel = pixels[y * image.getWidth() + x];
buffer.put((byte) ((pixel >> 16) & 0xFF)); // Red component
buffer.put((byte) ((pixel >> 8) & 0xFF)); // Green component
buffer.put((byte) (pixel & 0xFF)); // Blue component
buffer.put((byte) ((pixel >> 24) & 0xFF)); // Alpha component. Only for RGBA
}
}
buffer.flip(); //FOR THE LOVE OF GOD DO NOT FORGET THIS
// You now have a ByteBuffer filled with the color data of each pixel.
// Now just create a texture ID and bind it. Then you can load it using
// whatever OpenGL method you want, for example:
int textureID = GL11.glGenTextures(); //Generate texture ID
GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID); //Bind texture ID
//Setup wrap mode
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
//Setup texture scaling filtering
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
//Send texel data to OpenGL
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, image.getWidth(), image.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);
buffer = null;
//Return the texture ID so we can bind it later again
return textureID;
}
}
我知道,代码很多,但如果有人能帮助我,我将不胜感激。
谢谢,Flafla2。
最佳答案
以为你已经解决了这个问题,还有更多改进的空间。我看到你的字体在图像中,对于你想要绘制的每个字符,你都会得到带有该字母的图像部分,将其加载到纹理中,然后所有需要清理的内容。
最好将整个图像加载到一个大纹理中,在程序运行期间保留该纹理,并在渲染每一帧时重复使用它。您可以通过指定正确的纹理坐标来选择要渲染的正确字符。
除非您的 MacBook 非常旧,否则您应该能够在 CPU 使用率较低的情况下达到 60fps 上限。
关于java - 提高 LWJGL 游戏性能的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9648912/
我正在比较工作簿中的工作表。该工作簿有两张名为 PRE 和 POST 的工作表,每张工作表都有相同的 19 列。行数每天都不同,但特定一天的两张表的行数相同。该宏将 PRE 工作表中的每一行与 POS
我有一个对象数组,我一次循环遍历该数组一个对象,然后进行几次检查以查看该数组中的每个对象是否满足特定条件,如果该对象满足此条件,则复制一个属性将此对象放入数组中(该属性还包含另一个对象)。 for(v
我正在编写一个必须非常快的应用程序。我使用 Qt 5.5 和 Qt Creator,Qt 的 64 位 MSVC2013 编译版本。 我使用非常困倦的 CS 来分析我的应用程序,我看到占用最多独占时间
我有以下 CountDownTimer 在我的 Android 应用程序中不断运行。 CountDownTimer timer_status; timer_status = new CountDown
有一个优化问题,我必须调用随机森林回归器的预测函数数千次。 from sklearn.ensemble import RandomForestRegressor rfr = RandomForestR
我正在努力提高现有 Asp.Net Web 应用程序的数据访问层的性能。场景是。 它是一个基于 Web 的 Asp.Net 应用程序。 数据访问层使用 NHibernate 1.2 构建并作为 WCF
我在我的 Intel Edison 上运行 Debian,并尝试使用 ffmpeg 通过 USB 网络摄像头捕获视频。我正在使用的命令是: ffmpeg -f video4linux2 -i /dev
我有一个 For循环遍历整数 1 到 9 并简单地找到与该整数对应的最底部的条目(即 1,1,1,2,3,4,5 将找到第三个“1”条目)并插入一个空白行。我将数字与仅对应于此代码的应用程序的字符串“
我有一个带有非规范化架构(1 个表)的 postgresql 数据库,其中包含大约 400 万个条目。现在我有这个查询: SELECT count(*) AS Total, (SELECT c
在 Ltac 中实现复杂的策略时,有一些 Ltac 命令或策略调用我预计会失败以及预期失败(例如终止 repeat 或导致回溯)。这些故障通常在故障级别 0 时引发。 更高级别引发的故障“逃避”周
我正在尝试提高 ansible playbook 的性能。我有一个测试剧本如下: --- - name: Test hosts: localhost connection: local g
我正在使用 axios从 Azure 存储 Blob 下载文件 (~100MB)。 axios({ method: 'get', url: uri, onDownloadProgress:
我有一个 ClojureScript 程序,主要对集合执行数学计算。它是在惯用的、独立于主机的 Clojure 中开发的,因此很容易对其进行基准测试。令我惊讶的是(与答案对 Which is fast
我有一个程序必须在硬件允许的情况下尽快发出数千个 http 请求。在现实世界中,这些连接中的每一个都将连接到一个离散的服务器,但我已经编写了一个测试程序来帮助我模拟负载(希望如此)。 我的程序使用 A
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我正在计算 Clojure 中 3d 点云的边界框。点云表示为 Java 原始浮点数组,点云中的每个点都使用 4 个浮点存储,其中最后一个浮点未使用。像这样: [x0 y0 z0 u0 x1 y1
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我正在尝试使用rayshader 包制作图像。我很高兴能够使用如下代码创建一个 png 文件: library(ggplot2) library(rayshader) example_plot <-
更新 显然,jQuery 模板可以被编译,并且它有助于显示带有 if 语句 的模板的性能 here . 但是如图here ,预编译的 jQuery 模板对我的情况没有多大作用,因为我的模板不包含逻辑
我是编程新手。我有一个启用分页的 ScrollView ,其中包含许多页面(最多十个),并且在每个页面上都有一个自定义按钮。每个自定义按钮都有一个自定义图像。我在 Interface Builder
我是一名优秀的程序员,十分优秀!