I have a problem, I have some code that crashes the app but I don’t know where it is. Often to debug I will use prints and errors to find the problem but I can’t do that if the app crashes, any tips on how to find my bug?
If the app crashes back to iOS and you can’t see normal print statements, you can use something like save project data to save some info. After the app crashed you can restart the app and read project data to see what you saved.
@ellie_ff1493 it would really help if you showed us the code. If you don’t want to, then to add on to what @dave1707 said, look at all the code that is outside of functions, and look at the setup function. Those two are most prone to causing crashes
Actually, the thing that causes a Codea program to crash the most is using too much memory before it can be cleared. Just for kicks, add the statement collectgarbage()
at the beginning of the draw() function and see if the app still crashes. If it doesn’t, then it’s a memory issue. Are you drawing/creating a lot of images or using the camera to create images. Those usually cause a crash.
@dave1707 You are correct, except he is saying that the program isn’t even starting up because it crashes immediately. I don’t think the program gets a chance to make it to the draw() function
@CamelCoder Where does it say that the app crashes on startup. I read that it crashes but they don’t know where. They said they would put print statement in the code but they can’t because the app crashes. So, does it crash back to iOS. If that’s the case, then using saveprojectdata might help because you can go back and see what was saved. As you mentioned, it would help if we could see some code or at least have more information about what’s happening.
Here is the code
Bubbles = class()
function Bubbles:init(x, y)
-- Initialising our bubble emitter
self.x = x
self.y = y
self.bubbles = {}
self.maxbubbles = 100
self.bubblecount = 0
m = mesh()
m.shader = shader("Project:Stck")
m:addRect(WIDTH/2, HEIGHT/2, WIDTH-50, HEIGHT-50)
self.m = m
end
function Bubbles:emit()
-- Make sure we don't emit more than maxbubbles
if self.bubblecount < self.maxbubbles then
local dir = vec2(0,1):rotate(math.random() - 0.5) * math.random(1,6)
local size = math.random(10, 50)
local life = math.random(30, 60)
local bubble = {pos = vec2(self.x, self.y),
dir = dir,
size = size,
life = life}
-- Bubbles have the following properties
-- dir: direction
-- size: size of the bubble
-- life: how many frames the bubble lives
-- pos: the initial position of the bubble
-- (all bubbles start at the emitter position)
-- Add the bubble to our table of bubbles
table.insert(self.bubbles, bubble)
-- Keep track of how many bubbles we have
self.bubblecount = self.bubblecount + 1
end
end
-- This function updates all the bubbles in the system
function Bubbles:update()
-- Loop through bubbles
for k,v in pairs(self.bubbles) do
-- Add direction of bubble to its
-- position, to generate new position
v.pos = v.pos + v.dir
-- Subtract one from its life
v.life = v.life - 1
-- If this bubble's life is 0
if v.life == 0 then
-- Remove it from the table
self.bubbles[k] = nil
-- Reduce our bubble count
-- (we can emit more now!)
self.bubblecount = self.bubblecount - 1
end
end
end
-- This function draws all the bubbles in the system
function Bubbles:draw()
-- Store current style
pushStyle()
-- Set up our bubble style
ellipseMode(CENTER)
stroke(255)
strokeWidth(4)
fill(153, 197, 210, 100)
-- Loop through bubbles and draw them
arr = {}
for i = 0, 99 do
v = self.bubbles[i]
if v==nil then
table.insert(arr, vec2(0,0))
else
table.insert(arr, vec2(v.pos.x/WIDTH, v.pos.y/HEIGHT))
end
end
-- print(#arr)
self.m.shader.points = arr
self.m.shader.len = #self.bubbles
self.m:draw()
for k,v in pairs(self.bubbles) do
-- ellipse(v.pos.x, v.pos.y, v.size)
end
-- Restore original style
popStyle()
end
-- Use this function to perform your initial setup
function setup()
displayMode(OVERLAY)
-- Create a global bubble emitter
emitter = Bubbles(0, 0)
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)
-- This sets the line thickness
strokeWidth(5)
-- Do your drawing here
fill(255)
text("Drag your finger to make bubbles", WIDTH/1.5, HEIGHT - 40)
-- Update and draw bubbles
emitter:update()
emitter:draw()
end
-- This function gets called whenever a touch event occurs
function touched(touch)
-- Whenever the screen encounters a touch event we:
-- update the emitter position
-- emit a single bubble
emitter.x = touch.x
emitter.y = touch.y
emitter:emit()
-- Touch events happen when your finger moves, begins
-- touching or ends touching
end
And the fragment shader
precision highp float;
uniform vec2 points[100];
uniform int len;
varying lowp vec4 vColor;
//The interpolated texture coordinate for this fragment
varying highp vec2 vTexCoord;
void main(){
float num = 0.;
for (int i=0; i<len; i++){
num += 0.02 / distance(vTexCoord, points[i])+0.00001;
}
if (num > .8) {
gl_FragColor = vec4(1,1,1,1);
}
else{
gl_FragColor = vec4(0,0,0,1);
}
}
I have also narrowed it down.
If I stop the code by pressing back it will crash but if I stop the code it’s less likely to crash.
If I resize the console it will crash
@ellie_ff1493 Your code ran without crashing, but it didn’t do anything. I made some changes so it would work. At least I think this is what it’s supposed to do. I took all the comments out just to shorten the repost. I’m not sure how you were doing the shader, but I changed it to the way I use shaders.
displayMode(FULLSCREEN)
function setup()
emitter = Bubbles(0, 0)
end
function draw()
background(40, 40, 50)
fill(255)
text("Drag your finger to make bubbles", WIDTH/2, HEIGHT - 40)
emitter:update()
emitter:draw()
end
function touched(touch)
emitter.x = touch.x
emitter.y = touch.y
emitter:emit()
end
Bubbles = class()
function Bubbles:init(x, y)
self.x = x
self.y = y
self.bubbles = {}
self.maxbubbles = 100
self.bubblecount = 0
m = mesh()
m.shader = shader(sh.v,sh.f)
m:addRect(WIDTH/2, HEIGHT/2, WIDTH-50, HEIGHT-50)
self.m = m
end
function Bubbles:emit()
if self.bubblecount < self.maxbubbles then
local dir = vec2(0,1):rotate(math.random() - 0.5) * math.random(1,6)
local size = math.random(10, 50)
local life = math.random(30, 60)
local bubble = {pos = vec2(self.x, self.y),
dir = dir,
size = size,
life = life}
table.insert(self.bubbles, bubble)
self.bubblecount = #self.bubbles
end
end
function Bubbles:update()
for k,v in pairs(self.bubbles) do
v.pos = v.pos + v.dir
v.life = v.life - 1
if v.life == 0 then
self.bubbles[k] = nil
self.bubblecount = self.bubblecount - 1
end
end
end
-- This function draws all the bubbles in the system
function Bubbles:draw()
ellipseMode(CENTER)
stroke(255)
strokeWidth(4)
fill(153, 197, 210, 100)
arr = {}
for i = 0, 99 do
v = self.bubbles[i]
if v==nil then
table.insert(arr, vec2(0,0))
else
table.insert(arr, vec2(v.pos.x/WIDTH, v.pos.y/HEIGHT))
end
end
self.m.shader.points = arr
self.m.shader.len = #self.bubbles
self.m:draw()
for k,v in pairs(self.bubbles) do
ellipse(v.pos.x, v.pos.y, v.size)
end
end
sh =
{ v=[[
uniform mat4 modelViewProjection;
attribute vec4 position;
void main()
{ gl_Position = modelViewProjection * position;
}
]],
f=[[
precision highp float;
uniform vec2 points[100];
uniform int len;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
void main()
{ float num = 0.;
for (int i=0; i<len; i++)
num += 0.02 / distance(vTexCoord, points[i])+0.00001;
if (num > .8)
gl_FragColor = vec4(1,1,1,1);
else
gl_FragColor = vec4(0,0,0,1);
}
]]
}
It didn’t do anything because the shader wasn’t running
Here is the correct code in your format
It is a bit more stable but still crashes
displayMode(FULLSCREEN)
function setup()
emitter = Bubbles(0, 0)
end
function draw()
background(40, 40, 50)
fill(255)
text("Drag your finger to make bubbles", WIDTH/2, HEIGHT - 40)
emitter:update()
emitter:draw()
end
function touched(touch)
emitter.x = touch.x
emitter.y = touch.y
emitter:emit()
end
Bubbles = class()
function Bubbles:init(x, y)
self.x = x
self.y = y
self.bubbles = {}
self.maxbubbles = 100
self.bubblecount = 0
m = mesh()
m.shader = shader(sh.v,sh.f)
m:addRect(WIDTH/2, HEIGHT/2, WIDTH-50, HEIGHT-50)
self.m = m
end
function Bubbles:emit()
if self.bubblecount < self.maxbubbles then
local dir = vec2(0,1):rotate(math.random() - 0.5) * math.random(1,6)
local size = math.random(10, 50)
local life = 600
local bubble = {pos = vec2(self.x, self.y),
dir = dir,
size = size,
life = life}
table.insert(self.bubbles, bubble)
self.bubblecount = #self.bubbles
end
end
function Bubbles:update()
for k,v in pairs(self.bubbles) do
v.pos = v.pos + v.dir
v.life = v.life - 1
if v.life == 0 then
self.bubbles[k] = nil
self.bubblecount = self.bubblecount - 1
end
end
end
-- This function draws all the bubbles in the system
function Bubbles:draw()
ellipseMode(CENTER)
stroke(255)
strokeWidth(4)
fill(153, 197, 210, 100)
arr = {}
for i = 0, 99 do
v = self.bubbles[i]
if v==nil then
table.insert(arr, vec2(0,0))
else
table.insert(arr, vec2(v.pos.x/WIDTH, v.pos.y/HEIGHT))
end
end
self.m.shader.points = arr
self.m.shader.len = #self.bubbles
self.m:draw()
end
sh =
{ v=[[
uniform mat4 modelViewProjection;
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
void main()
{
vColor = color;
vTexCoord = texCoord;
gl_Position = modelViewProjection * position;
}
]],
f=[[
precision highp float;
uniform vec2 points[100];
uniform int len;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
void main()
{ float num = 0.;
for (int i=0; i<len; i++)
num += 0.02 / distance(vTexCoord, points[i])+0.00001;
if (num > .8)
gl_FragColor = vec4(1,1,1,1);
else
gl_FragColor = vec4(0,0,0,1);
}
]]
}
@ellie_ff1493 When I get it to run, it has a bubble/blob that acts like what’s in a lava lamp. It looks really nice, but still crashes after awhile. I don’t know enough about shaders, so I can’t say why it crashes. When you work with shaders, be prepared to debug blind because you won’t get any information other than a crash if things don’t work right. You never said what this program is really supposed to do.
I fixed it, turns out 100 is to large of an array size, I changed it to 10 and it’s really stable now
I looked in to it some more and it’s not the large array it just makes the bug worse, the problem is using a uniform variable in a for loop because it try’s to unroll the loop but can’t because it’s an unknown when it compiles. This also makes a bug where different parts of the screen get rendered in different places like in the pic