I found that the I2C interface is very slow on the ESP8266 (but better on an ESP32). There is NO hardware support for I2C and the interface uses a technique called "bit banging". This is very wasteful of processor resources but needed if there is no hardware support.
My response: minimize I2C usage. I changed the way the display is handled so that I only paint the part of the display that I'm updating. That is an option that can be selected by the constructor used with the U8g2 graphics library. My original usage was to fill a buffer with the display that I wanted next then transfer that entire buffer to the OLED. Now the program is only sending the parts of the screen that it needs to change.
In addition, I only display the content of a command datagram when the content is much different than the previous datagram. The datagram display or datagram count (two program actions that can be selected at compile time) are only a debugging aid and not needed to drive the car around.
One other small change - while the program is trying to acquire a WiFi connection and an IP address, the display is shows "connecting" and the blue LED on the ESP12 itself will flash as it tries to connect. This will show it is running and not powered off. A flaky power switch on my car made this useful.
Another small change - I removed the car's R5 and R6 51 ohm resistors. These power the bottom LEDs that would light up the lines so we could follow them. Since we are controlling the car directly, this power can be saved. I put pins in the holes from the resistors so that I can plug resistors back on these pins to restore line-following function.
When I use the UDP Joystick app with the correct IP address (as shown on the display at startup), with port set to 4949, and Send Delay set to 200ms, the car drives easily. I'm very pleased!
Again, note that in the app configuration I selected "Center On Release" for all four directions and selected Reverse Value for the Left Vertical.
Final name of this revised version ESPPackU8X8.ino.