Image slowly offsetting itself

First ever post so sorry if I phrase this poorly.

Have written a PONG game that uses pixel flow data from a webcam to move the paddle. It ran fine for months without issue on multiple PCs (both Windows 10 and 11) but has recently developed a strange bug where the entire image on screen ‘offsets’ upwards after a few minutes/hours/days (it seems totally fine when the application is first opened).

In other words the entire image (the video feed and the paddle/ball) slides up the screen with the first few inches from the top now on the bottom. Have tried reinstalling the video library, re-compiling, updating Windows, updating the video drivers and nothing seems to fix it. Does anybody have any ideas how to fix it?

import processing.sound.*;
import gab.opencv.*;
import processing.video.*;

OpenCV opencv;
Capture video;

float movement = 0;
PImage[] hole = new PImage[9];
PImage[] hole2 = new PImage[9];
PImage[] hole3 = new PImage[9];
PImage winImg;

SoundFile crackSound;
SoundFile bounce;
SoundFile chortle;
SoundFile win;

float x = 0;
float y = 0;
float x_speed = 4;
float y_speed = 4;

int scale = 2; 
int x_paddle, y_paddle;
int paddle_width_half = 35;
int paddle_height = 11;

int breakCount = 0;

int framecount = 1;
int sequence = 1;

boolean winState = false;
int winTime = 0;

void setup() {

fullScreen();
//size(800, 600);
rectMode(CENTER);

crackSound = new SoundFile(this, "crack.wav");
bounce = new SoundFile(this, "bounce.wav");
chortle = new SoundFile(this, "chortle.wav");
win = new SoundFile(this, "win.wav");

x_paddle = 0; 
y_paddle = (height/scale)-15;

noCursor();

winImg = loadImage("win.png");

hole[0] = loadImage("hole0.png");
hole[1] = loadImage("hole1.png");
hole[2] = loadImage("hole2.png");
hole[3] = loadImage("hole3.png");
hole[4] = loadImage("hole4.png");
hole[5] = loadImage("hole5.png");
hole[6] = loadImage("hole6.png");
hole[7] = loadImage("hole7.png");
hole[8] = loadImage("hole8.png");

hole2[0] = loadImage("2hole0.png");
hole2[1] = loadImage("2hole1.png");
hole2[2] = loadImage("2hole2.png");
hole2[3] = loadImage("2hole3.png");
hole2[4] = loadImage("2hole4.png");
hole2[5] = loadImage("2hole5.png");
hole2[6] = loadImage("2hole6.png");
hole2[7] = loadImage("2hole7.png");
hole2[8] = loadImage("2hole8.png");

hole3[0] = loadImage("3hole0.png");
hole3[1] = loadImage("3hole1.png");
hole3[2] = loadImage("3hole2.png");
hole3[3] = loadImage("3hole3.png");
hole3[4] = loadImage("3hole4.png");
hole3[5] = loadImage("3hole5.png");
hole3[6] = loadImage("3hole6.png");
hole3[7] = loadImage("3hole7.png");
hole3[8] = loadImage("3hole8.png");


video = new Capture(this, width/2, height/2, "pipeline:autovideosrc");
opencv = new OpenCV(this, 400, 300);
video.start();

stroke(0);
strokeWeight(1);
frameRate(18);
}


void draw() {
  
scale(scale);
image(video,0,0);
if(framecount == 1){
opencv.loadImage(video);
opencv.calculateOpticalFlow();
PVector aveFlow = opencv.getAverageFlow();
if (aveFlow.x > 0.2f || aveFlow.x < -0.2f ){
   
movement = movement + (aveFlow.x * 25);
          
}

framecount = 0;
}

if(winState){
  winTime=winTime+3;
  
   if(sequence == 1){
    image(hole[8],0,0);
  }
  if(sequence ==2){
    image(hole2[8],0,0);
  }
  if(sequence ==3){
    image(hole3[8],0,0);
  }
  tint(255,winTime);
  image(winImg,0,0);
  
  if(winTime >= 255){
   winTime = 0;
   winState = false;
  }
}

if (breakCount ==9){
  win.play();
  winState = true;
  y_speed = 4;
  x_speed = 4;
  sequence++;
 breakCount = 0; 
}

if (sequence ==4){
  sequence = 1;
}
 //Shatter glass effect
if (breakCount >= 1){

  if(sequence == 1){
    image(hole[breakCount-1],0,0);
  }
  if(sequence ==2){
    image(hole2[breakCount-1],0,0);
  }
   if(sequence ==3){
    image(hole3[breakCount-1],0,0);
  }

}

//opencv.drawOpticalFlow();

if (movement > (width/scale)-paddle_width_half){
 movement = (width/scale)-paddle_width_half; 
}

if (movement < (paddle_width_half)){
 movement = paddle_width_half; 
}

rect(x_paddle + movement, y_paddle, paddle_width_half*2+1, paddle_height);

ellipse(x, y, 10, 10);

 x = x + x_speed;

  y = y + y_speed;

  if (x>width/scale || x<0)  {
    
     bounce.play();
     x_speed = -x_speed;
  }

if(!winState){
  if (y<0){
     y_speed = -y_speed;
      breakCount++;
      crackSound.play(); 
  }
}

if ((x_paddle+movement-paddle_width_half-10)<x && (x_paddle+movement+paddle_width_half+10)>x && 

    (y_paddle-paddle_height)<y && (y_paddle)>y) {

    // ball is hitting paddle rectangle, reverse y_speed

    y_speed = -y_speed*1.1*random(1,1.1);
    x_speed = x_speed*1.1*random(1,1.1);
    bounce.play();

}

if (y>height/scale*1.2) {

x = 250 + int(random(-120,120));
y = 0;
y_speed = 4;
x_speed = 4;
if(breakCount >0){
  chortle.play();
}
breakCount = 0;
sequence++;

}

framecount++;
println(frameRate);
}


void captureEvent(Capture c) {

  c.read();

}

Welcome to the forum.

I have never known software to develop a bug unless the programmer has made changes to the code.

For future reference when posting code for others to read please note

  1. Format the code in Processing (Ctrl + T) before copying it to the forum - your code has irregular indentation which makes it really difficult to follow the code logic.
  2. The code posted is too long and can’t be executed. In this situation try and create a small executable sketch that demonstrates the problem.

It is unlikely that these are the cause of the problem it is almost certainly a logic bug in the sketch code. As I said you have over 200 lines of code that I can’t run because I don’t have the graphics and sound files.

I have looked at the code and the only thing I can see is that you don’t appear to clear the background for each frame so the display is built up with each call to draw. Most sketch animation makes the use of the background(...) method being called at the start of draw()

1 Like

Hi! Thanks for your reply.

I have never known software to develop a bug unless the programmer has made changes to the code.

It worked for around 6 months with zero changes to code before first showing the issue (the machine that runs it is literally behind a wall so it was impossible for the code to be changed) . I then recompiled it and it went away for a few more months but now I seem to be stuck with it. This made me think it was nothing to do with the code. But then again, maybe some rare occurrence in the code causes the offset (and the code is messy as you say). Thing is, moving the image up would just leave blank/static pixels at the bottom? I wouldn’t even know how to wrap the image around they way it does if I tried.

In any case I will try using background method and generally tidy up the code and see if it still happens - thanks again for your help!

Try commenting out all code related to the video library and see if that solves the problem. If it does it would suggest that the problem is with the video library.

1 Like

After more investigation: It is only the video feed that offsets, nothing else. Running the program in Processing itself seems fine… the code ran for weeks without offsetting. Also, we managed to catch the offset on camera and it happens nearly instantly (i.e. it doesn’t slowly slide up, it just jumps to a seemingly random position any point from a few minutes to a few hours after the exported app begins).

As such we can use the workaround of running the code in processing for now but I would be very grateful if anybody has any ideas for a less clunky fix.