Is the video game movie curse lifting?

TidyTuesday 2026-06-09 · Films based on video games (Wikipedia)

Published

June 9, 2026

TipSession 1 · co-developed

This page came out of a live, turn-by-turn conversation between Jon Minton and Claude (Fable 5) — questions, plots and interpretation built together in real time. The Session 2 pages were instead produced by Claude working autonomously.

A fast (~15 minute) second session. 439 films adapted from video games, 1993–2026: theatrical releases, direct-to-video, TV films, shorts and documentaries, with box office, budgets and critic/audience scores where Wikipedia has them.

WarningThe ¥5 billion Pokémon trap

Sort this dataset by worldwide_box_office and the top eight films of all time are all Pokémon features at “$4–5 billion” — each apparently out-grossing Avatar. They didn’t: those rows are denominated in yen (see worldwide_box_office_currency). ¥5.02bn ≈ $43m. Every box-office figure below uses dollar-denominated rows only.

Code
library(tidyverse)

films <- read_csv("data/game_films.csv", show_col_types = FALSE)

theatrical <- films |>
  filter(category == "Theatrical releases", !is.na(release_date)) |>
  mutate(
    year = year(release_date),
    box_usd = if_else(worldwide_box_office_currency == "$",
                      worldwide_box_office, NA_real_)
  )

theme_set(theme_minimal(base_size = 13))

The curse, and its apparent lifting

For its first twenty-five years, the video game adaptation was a critical punchline: Super Mario Bros. (1993) set the tone at 29% on Rotten Tomatoes, and the mid-2000s Uwe Boll era dragged the median into the teens.

Code
notable <- c("Super Mario Bros.", "The Super Mario Bros. Movie",
             "Sonic the Hedgehog 3", "Pokémon Detective Pikachu",
             "Warcraft", "A Minecraft Movie", "Alone in the Dark")

lab <- theatrical |> filter(title %in% notable, !is.na(rotten_tomatoes))

theatrical |>
  filter(!is.na(rotten_tomatoes)) |>
  ggplot(aes(release_date, rotten_tomatoes)) +
  geom_hline(yintercept = 60, linetype = "dashed", colour = "grey55") +
  annotate("text", x = as.Date("1994-01-01"), y = 63,
           label = "“fresh” threshold", hjust = 0, size = 3.2, colour = "grey45") +
  geom_smooth(method = "loess", se = TRUE, colour = "grey40",
              fill = "grey88", linewidth = 0.8) +
  geom_point(aes(size = box_usd / 1e6), shape = 21,
             fill = "#e08214", colour = "grey25", alpha = 0.75) +
  geom_text(data = lab, aes(label = title), size = 3,
            vjust = -1.4, fontface = "italic", check_overlap = TRUE) +
  scale_size_area(max_size = 14, name = "Worldwide box office ($m)",
                  breaks = c(100, 500, 1000)) +
  scale_y_continuous(limits = c(0, 100)) +
  labs(
    title = "Three decades of rotten, then a corner turned around 2019",
    subtitle = "The big money arrived at the same moment as the respectable reviews",
    x = NULL, y = "Rotten Tomatoes score"
  ) +
  theme(legend.position = "bottom")

Rotten Tomatoes score by release date for theatrical releases. Point area = worldwide box office (dollar-denominated films); hollow points lack box office data.

The median Rotten Tomatoes score by half-decade tells it crisply: 17–20 from the 1990s through the late 2000s, 40 in the late 2010s, 57 in 2020–24. And the box office bubbles cluster in the top-right: the films that finally earned serious money (The Super Mario Bros. Movie, $1.36bn; A Minecraft Movie; the Sonic series) are also the ones critics stopped hating — or at least, stopped flunking.

Do audiences agree with critics? Not even slightly

CinemaScore polls opening-night audiences — people who chose to be there. Compare those letter grades with Rotten Tomatoes:

Code
grade_levels <- c("F", "D", "D+", "C-", "C", "C+", "B-", "B", "B+", "A-", "A", "A+")
grade_score  <- set_names(seq(0, 100, length.out = 12), grade_levels)

cs <- films |>
  filter(!is.na(cinema_score), cinema_score != "N/A",
         !is.na(rotten_tomatoes)) |>
  mutate(
    cs_num = grade_score[cinema_score],
    gap = cs_num - rotten_tomatoes
  )

ggplot(cs, aes(rotten_tomatoes, cs_num)) +
  geom_abline(slope = 1, intercept = 0, linetype = "dashed", colour = "grey55") +
  annotate("text", x = 78, y = 70, label = "audiences and critics agree",
           angle = 38, size = 3.2, colour = "grey45") +
  geom_point(colour = "#7b3294", size = 2.5, alpha = 0.8) +
  geom_text(data = \(d) slice_max(d, gap, n = 3),
            aes(label = title), size = 3, vjust = -0.9, check_overlap = TRUE) +
  scale_y_continuous(breaks = grade_score[c("F", "C", "B", "A")],
                     labels = c("F", "C", "B", "A")) +
  labs(
    title = "Opening-night audiences grade a full letter (or three) above critics",
    subtitle = "Each point is a film with both scores; almost everything sits above the agreement line",
    x = "Rotten Tomatoes (critics)", y = "CinemaScore (audiences)"
  )

CinemaScore (opening-night audiences) vs Rotten Tomatoes (critics). The diagonal maps letter grades onto an equivalent 0–100 scale.
Code
cs |>
  summarise(
    films = n(),
    `median critic score` = median(rotten_tomatoes),
    `median audience grade` = names(grade_score)[
      which.min(abs(grade_score - median(cs_num)))],
    `films above the line` = sum(gap > 0)
  ) |>
  knitr::kable()
films median critic score median audience grade films above the line
51 29 B 45

Part of this is selection — CinemaScore samples fans on opening night, and its scale is famously compressed (a “B” is a mediocre result by its norms). But the size of the gap here is still striking: these were films made for an audience critics weren’t part of. The 2019-onward turnaround in the first chart may be less “films got better” and more “studios finally made the films the CinemaScore audience always wanted — competently.”

Where next

With more time: deflate box office to constant dollars; model the review-revenue relationship with budget as a control (budget data exist for ~15% of rows); and test whether franchise familiarity (Wikipedia’s original_game_publisher as a proxy) predicts the audience–critic gap.